// 全局变量
let db = null;
let currentMapping = {
    aTable: { name: '', fields: [] },
    bTable: { name: '', fields: [] },
    mappings: []
};
let canvas = null;
let ctx = null;

// 新增变量
let currentBatchTableType = '';
let selectedConnection = null;
let connections = [];
let filteredAFields = [];
let filteredBFields = [];

// 拖拽相关变量
let isDragging = false;
let dragStartPoint = null;
let dragEndPoint = null;
let tempConnection = null;
let selectedFieldCard = null;

// 选中状态相关变量
let selectedTable = null; // 'A', 'B', 或 null

// 数据变化和自动保存相关变量
let hasUnsavedChanges = false;
let lastSavedData = null;
let autoSaveInterval = null;
let isUserClosing = false;

// SQL模板配置相关变量
let sqlTemplates = {
    // 字符串类型
    string_notnull: "'${json.field_name}'",
    string_nullable: "'${json.field_name!}'",

    // 数值类型
    numeric_notnull: "${json.field_name}",
    numeric_nullable: "<#if json.field_name??>${json.field_name}<#else>NULL</#if>",

    // 时间类型
    date_notnull: "cast('${json.field_name}' as datetime)",
    date_nullable: "<#if json.field_name??>cast('${json.field_name}' as datetime)<#else>NULL</#if>",

    // 整体拼接模板
    merge_template: "insert into 【TABLE_NAME】 [INSERT_VALUES_FORMAT] ON CONFLICT (yljgdm, jclsh, xgbz) DO UPDATE SET [MERGE_SET_FORMAT]"
};

// G6相关变量
let sankeyGraph = null;
let sankeyData = {
    nodes: [],
    edges: []
};

// 初始化数据库
async function initDatabase() {
    try {
        const SQL = await initSqlJs({ locateFile: file => `./${file}` });

        // 从localStorage加载已有数据库
        const savedDb = localStorage.getItem('mappingDB');
        if (savedDb) {
            try {
                const uInt8Array = new Uint8Array(JSON.parse(savedDb));
                db = new SQL.Database(uInt8Array);

                // 验证数据库结构
                validateAndCreateTables();
                updateDBInfo('已加载localStorage数据库');
                console.log('从localStorage成功加载数据库');
            } catch (parseError) {
                console.warn('localStorage数据库解析失败，创建新数据库:', parseError);
                db = new SQL.Database();
                createTables();
                updateDBInfo('localStorage数据库损坏，已创建新数据库');
                // 保存新的空数据库到localStorage
                saveDatabase();
            }
        } else {
            db = new SQL.Database();
            createTables();
            updateDBInfo('已创建新数据库');
        }

        console.log('数据库初始化成功');
        loadHistory();
    } catch (error) {
        console.error('数据库初始化失败:', error);
        showMessage('数据库初始化失败: ' + error.message, 'danger');
    }
}

// 验证数据库结构并创建缺失的表
function validateAndCreateTables() {
    try {
        // 检查table_mappings表是否存在
        const checkTableStmt = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='table_mappings'");
        const hasTableMappings = checkTableStmt.step();
        checkTableStmt.free();

        // 检查field_mappings表是否存在
        const checkFieldTableStmt = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='field_mappings'");
        const hasFieldMappings = checkFieldTableStmt.step();
        checkFieldTableStmt.free();

        if (!hasTableMappings || !hasFieldMappings) {
            console.log('检测到数据库表缺失，重新创建表结构');
            createTables();
        }
    } catch (error) {
        console.warn('验证数据库结构失败，重新创建表:', error);
        createTables();
    }
}

// 更新数据库信息显示
function updateDBInfo(status) {
    const dbPathSpan = document.getElementById('dbPath');
    if (dbPathSpan) {
        dbPathSpan.textContent = `浏览器localStorage - ${status}`;
    }
    updateDataStats();
}


// 更新数据统计信息
function updateDataStats() {
    try {
        // 获取映射记录数量
        const stmt = db.prepare('SELECT COUNT(*) as count FROM table_mappings');
        const result = stmt.getAsObject();
        const totalMappings = result.count;
        stmt.free();

        // 获取表数量
        const tableStmt = db.prepare('SELECT COUNT(DISTINCT a_table_name) + COUNT(DISTINCT b_table_name) as count FROM table_mappings');
        const tableResult = tableStmt.getAsObject();
        const totalTables = tableResult.count;
        tableStmt.free();

        // 计算localStorage使用情况
        let storageSize = 0;
        for (let key in localStorage) {
            if (localStorage.hasOwnProperty(key)) {
                storageSize += localStorage[key].length;
            }
        }
        const sizeKB = (storageSize / 1024).toFixed(2);

        // 获取最后备份时间
        const lastBackup = localStorage.getItem('lastBackupTime') || '从未';

        // 更新详细统计信息
        const statsElement = document.getElementById('dataStats');
        if (statsElement) {
            statsElement.innerHTML = `
                <i class="bi bi-info-circle"></i>
                数据库运行正常，共 <strong>${totalMappings}</strong> 个映射记录，涉及 <strong>${totalTables}</strong> 个表，
                占用存储 <strong>${sizeKB} KB</strong>
            `;
        }

        // 更新统计卡片
        document.getElementById('totalMappings').textContent = totalMappings;
        document.getElementById('totalTables').textContent = totalTables;
        document.getElementById('storageSize').textContent = `${sizeKB} KB`;
        document.getElementById('lastBackupTime').textContent = lastBackup.includes(':') ?
            lastBackup.split(' ')[1] + ' ' + lastBackup.split(' ')[2] : '从未';

    } catch (error) {
        console.error('更新数据统计失败:', error);
    }
}

// 创建表结构
function createTables() {
    const createTableMappings = `
        CREATE TABLE IF NOT EXISTS table_mappings (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            a_table_name TEXT NOT NULL,
            b_table_name TEXT NOT NULL,
            a_table_structure TEXT NOT NULL,
            b_table_structure TEXT NOT NULL,
            mappings TEXT NOT NULL,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )
    `;

    const createFieldMappings = `
        CREATE TABLE IF NOT EXISTS field_mappings (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            mapping_id INTEGER,
            a_field_name TEXT NOT NULL,
            b_field_name TEXT NOT NULL,
            a_field_comment TEXT,
            b_field_comment TEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            FOREIGN KEY (mapping_id) REFERENCES table_mappings (id)
        )
    `;

    db.run(createTableMappings);
    db.run(createFieldMappings);
}

// 保存数据库到localStorage
function saveDatabase() {
    try {
        const data = db.export();
        const dataArray = Array.from(data);

        // 检查数据大小
        const dataSize = JSON.stringify(dataArray).length;
        if (dataSize > 5 * 1024 * 1024) { // 5MB限制
            console.warn('数据库过大，可能导致localStorage保存失败');
            showMessage('数据库过大，建议清理历史记录', 'warning');
        }

        localStorage.setItem('mappingDB', JSON.stringify(dataArray));
        updateDataStats();
        console.log('数据库已保存到localStorage，大小:', (dataSize / 1024).toFixed(2), 'KB');
    } catch (error) {
        console.error('保存数据库到localStorage失败:', error);
        showMessage('数据库保存失败: ' + error.message, 'danger');
    }
}

// 保存当前映射到localStorage
function saveCurrentMapping() {
    const mappingData = {
        aTable: currentMapping.aTable,
        bTable: currentMapping.bTable,
        mappings: currentMapping.mappings,
        lastSaved: new Date().toISOString()
    };
    localStorage.setItem('currentMapping', JSON.stringify(mappingData));
}

// 从localStorage加载当前映射
function loadCurrentMapping() {
    const savedMapping = localStorage.getItem('currentMapping');
    if (savedMapping) {
        try {
            const mappingData = JSON.parse(savedMapping);
            currentMapping = mappingData;

            // 重新初始化过滤字段
            filteredAFields = currentMapping.aTable.fields.map(field => ({
                ...field,
                tableType: 'A',
                mapped: false,
                referenceCount: 0
            }));

            filteredBFields = currentMapping.bTable.fields.map(field => ({
                ...field,
                tableType: 'B',
                mapped: false
            }));

            // 更新映射状态
            currentMapping.mappings.forEach(mapping => {
                const aField = filteredAFields.find(f => f.name === mapping.aField);
                const bField = filteredBFields.find(f => f.name === mapping.bField);
                if (aField) {
                    aField.mapped = true;
                    aField.referenceCount = (aField.referenceCount || 0) + 1;
                }
                if (bField) {
                    bField.mapped = true;
                }
            });

            // 显示字段表格
            displayFieldsTable();
            renderSourceFieldsList();

            console.log('已从localStorage加载当前映射');
        } catch (error) {
            console.error('加载当前映射失败:', error);
        }
    }
}

// 导出数据库到本地文件
function exportDatabase() {
    try {
        // 获取所有映射记录
        const stmt = db.prepare(`
            SELECT id, a_table_name, b_table_name, a_table_structure, b_table_structure,
                   mappings, created_at, updated_at
            FROM table_mappings
            ORDER BY created_at DESC
        `);

        const allMappings = [];
        while (stmt.step()) {
            const record = stmt.getAsObject();
            // 解析表结构，使其更可读
            record.a_table_structure = JSON.parse(record.a_table_structure);
            record.b_table_structure = JSON.parse(record.b_table_structure);
            record.mappings = JSON.parse(record.mappings);
            allMappings.push(record);
        }
        stmt.free();

        // 创建可读的导出数据对象
        const exportData = {
            exportInfo: {
                version: '1.0',
                exportTime: new Date().toISOString(),
                exportDate: new Date().toLocaleString('zh-CN'),
                tool: '数据映射工具',
                description: '数据映射关系和表结构导出文件'
            },
            statistics: {
                totalMappings: allMappings.length,
                aTableCount: [...new Set(allMappings.map(m => m.a_table_name))].length,
                bTableCount: [...new Set(allMappings.map(m => m.b_table_name))].length
            },
            mappings: allMappings.map(record => ({
                id: record.id,
                tables: {
                    source: {
                        name: record.a_table_name,
                        fields: record.a_table_structure.fields.map(field => ({
                            name: field.name,
                            type: field.type,
                            comment: field.comment,
                            required: field.required
                        }))
                    },
                    target: {
                        name: record.b_table_name,
                        fields: record.b_table_structure.fields.map(field => ({
                            name: field.name,
                            type: field.type,
                            comment: field.comment,
                            required: field.required
                        }))
                    }
                },
                fieldMappings: record.mappings.map(mapping => ({
                    source: mapping.aField,
                    target: mapping.bField,
                    sourceComment: record.a_table_structure.fields.find(f => f.name === mapping.aField)?.comment || '',
                    targetComment: record.b_table_structure.fields.find(f => f.name === mapping.bField)?.comment || ''
                })),
                timestamps: {
                    created: record.created_at,
                    updated: record.updated_at,
                    createdFormatted: new Date(record.created_at).toLocaleString('zh-CN'),
                    updatedFormatted: new Date(record.updated_at).toLocaleString('zh-CN')
                }
            })),
            // 保留原始数据以便导入
            _importData: {
                version: '1.0',
                database: Array.from(db.export()),
                mappings: allMappings.map(record => ({
                    id: record.id,
                    a_table_name: record.a_table_name,
                    b_table_name: record.b_table_name,
                    a_table_structure: JSON.stringify(record.a_table_structure),
                    b_table_structure: JSON.stringify(record.b_table_structure),
                    mappings: JSON.stringify(record.mappings),
                    created_at: record.created_at,
                    updated_at: record.updated_at
                }))
            }
        };

        // 创建并下载文件
        const blob = new Blob([JSON.stringify(exportData, null, 2)], {
            type: 'application/json'
        });

        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `数据映射导出_${new Date().toISOString().split('T')[0]}.json`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);

        showMessage(`数据已导出，包含 ${allMappings.length} 个映射记录`, 'success');
    } catch (error) {
        console.error('导出数据失败:', error);
        showMessage('导出失败: ' + error.message, 'danger');
    }
}

// 导入数据库从本地文件
function importDatabase(file) {
    if (!file) return;

    const reader = new FileReader();
    reader.onload = function(e) {
        try {
            const importData = JSON.parse(e.target.result);

            // 支持新格式（可读）和旧格式
            let dataToImport = null;
            let recordCount = 0;

            if (importData._importData) {
                // 新格式：从_importData中读取
                dataToImport = importData._importData;
                recordCount = importData.statistics?.totalMappings || dataToImport.mappings.length;
            } else if (importData.database) {
                // 旧格式：直接使用
                dataToImport = importData;
                recordCount = importData.metadata?.totalMappings || importData.mappings?.length || 0;
            } else {
                throw new Error('无效的数据文件格式');
            }

            // 验证数据格式
            if (!dataToImport.version || !dataToImport.database) {
                throw new Error('数据文件格式无效或已损坏');
            }

            // 备份当前数据
            createAutoBackup();

            // 恢复数据库
            const SQL = window.initSqlJs ? window.initSqlJs : initSqlJs;
            SQL({ locateFile: file => `./${file}` }).then(function(SQLModule) {
                const uInt8Array = new Uint8Array(dataToImport.database);
                db = new SQLModule.Database(uInt8Array);

                // 保存到localStorage
                saveDatabase();

                // 重新加载历史记录
                loadHistory();

                showMessage(`数据导入成功，包含 ${recordCount} 个映射记录`, 'success');
            }).catch(function(error) {
                throw new Error('数据库初始化失败: ' + error.message);
            });

        } catch (error) {
            console.error('导入数据失败:', error);
            showMessage('导入失败: ' + error.message, 'danger');
        }
    };

    reader.readAsText(file);
}

// 创建备份
function createBackup() {
    try {
        const backupData = {
            timestamp: new Date().toISOString(),
            database: localStorage.getItem('mappingDB'),
            currentMapping: currentMapping
        };

        // 保存备份到localStorage
        localStorage.setItem(`backup_${Date.now()}`, JSON.stringify(backupData));
        localStorage.setItem('lastBackupTime', new Date().toLocaleString());

        // 同时导出文件
        const blob = new Blob([JSON.stringify(backupData, null, 2)], {
            type: 'application/json'
        });

        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `mapping-backup-${new Date().toISOString().split('T')[0]}.json`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);

        updateDataStats();
        showMessage('备份已创建并保存到本地文件', 'success');
    } catch (error) {
        console.error('创建备份失败:', error);
        showMessage('备份失败: ' + error.message, 'danger');
    }
}

// 自动备份
function createAutoBackup() {
    try {
        const backupData = {
            timestamp: new Date().toISOString(),
            database: localStorage.getItem('mappingDB'),
            currentMapping: currentMapping
        };

        // 只保留最近3个自动备份
        const keys = Object.keys(localStorage).filter(key => key.startsWith('autoBackup_'));
        if (keys.length >= 3) {
            keys.sort().slice(0, keys.length - 2).forEach(key => {
                localStorage.removeItem(key);
            });
        }

        localStorage.setItem(`autoBackup_${Date.now()}`, JSON.stringify(backupData));
        console.log('自动备份创建成功');
    } catch (error) {
        console.error('自动备份失败:', error);
    }
}

// 清理旧备份
function cleanupOldBackups() {
    try {
        const keys = Object.keys(localStorage).filter(key => key.startsWith('backup_') || key.startsWith('autoBackup_'));
        const maxBackups = 10;

        if (keys.length > maxBackups) {
            keys.sort().slice(0, keys.length - maxBackups).forEach(key => {
                localStorage.removeItem(key);
            });
        }
    } catch (error) {
        console.error('清理备份失败:', error);
    }
}

// Excel文件处理
function setupFileUpload() {
    // 源表文件上传
    const aTableFile = document.getElementById('aTableFile');
    const aTableDropZone = document.getElementById('aTableDropZone');

    aTableFile.addEventListener('change', (e) => {
        handleFileUpload(e.target.files[0], 'A');
    });

    // 目标表文件上传
    const bTableFile = document.getElementById('bTableFile');
    const bTableDropZone = document.getElementById('bTableDropZone');

    bTableFile.addEventListener('change', (e) => {
        handleFileUpload(e.target.files[0], 'B');
    });

    // 数据库导入文件上传
    const importDbFile = document.getElementById('importDbFile');
    if (importDbFile) {
        importDbFile.addEventListener('change', (e) => {
            importDatabase(e.target.files[0]);
            e.target.value = ''; // 重置文件输入
        });
    }

    // 拖拽功能
    setupDragAndDrop(aTableDropZone, 'A');
    setupDragAndDrop(bTableDropZone, 'B');
}

// 设置拖拽上传
function setupDragAndDrop(dropZone, tableType) {
    dropZone.addEventListener('dragover', (e) => {
        e.preventDefault();
        dropZone.style.background = '#e6f3ff';
    });

    dropZone.addEventListener('dragleave', (e) => {
        e.preventDefault();
        dropZone.style.background = '#f8f9ff';
    });

    dropZone.addEventListener('drop', (e) => {
        e.preventDefault();
        dropZone.style.background = '#f8f9ff';

        const files = e.dataTransfer.files;
        if (files.length > 0) {
            handleFileUpload(files[0], tableType);
        }
    });
}

// 处理文件上传
function handleFileUpload(file, tableType) {
    if (!file) return;

    const reader = new FileReader();
    reader.onload = function(e) {
        try {
            const data = new Uint8Array(e.target.result);
            const workbook = XLSX.read(data, { type: 'array' });
            const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
            const jsonData = XLSX.utils.sheet_to_json(firstSheet, { header: 1 });

            parseTableData(jsonData, tableType);
        } catch (error) {
            showMessage('文件解析失败: ' + error.message, 'danger');
        }
    };
    reader.readAsArrayBuffer(file);
}

// 解析表数据
function parseTableData(data, tableType) {
    if (data.length < 2) {
        showMessage('Excel文件格式不正确，至少需要包含表头和一行数据', 'warning');
        return;
    }

    const headers = data[0];
    const fields = [];

    // 查找序号、列名、注释、数据类型、排序规则、非空、默认值、标识等列
    const seqIndex = headers.findIndex(h => h && h.toString().toLowerCase().includes('序号') || h && h.toString().toLowerCase().includes('#'));
    const colNameIndex = headers.findIndex(h => h && h.toString().toLowerCase().includes('列名'));
    const commentIndex = headers.findIndex(h => h && h.toString().toLowerCase().includes('注释'));
    const typeIndex = headers.findIndex(h => h && h.toString().toLowerCase().includes('数据类型'));
    const collationIndex = headers.findIndex(h => h && h.toString().toLowerCase().includes('排序规则'));
    const nullableIndex = headers.findIndex(h => h && h.toString().toLowerCase().includes('非空'));
    const defaultIndex = headers.findIndex(h => h && h.toString().toLowerCase().includes('默认值'));
    const identityIndex = headers.findIndex(h => h && h.toString().toLowerCase().includes('标识'));

    if (colNameIndex === -1) {
        showMessage('未找到"列名"列，请检查Excel格式', 'warning');
        return;
    }

    // 解析字段数据
    for (let i = 1; i < data.length; i++) {
        const row = data[i];
        if (row[colNameIndex]) {
            const field = {
                name: row[colNameIndex].toString().trim(),
                comment: commentIndex !== -1 && row[commentIndex] ? row[commentIndex].toString().trim() : '',
                type: typeIndex !== -1 && row[typeIndex] ? row[typeIndex].toString().trim() : 'VARCHAR',
                collation: collationIndex !== -1 && row[collationIndex] ? row[collationIndex].toString().trim() : '',
                required: nullableIndex !== -1 && row[nullableIndex] ? isRequiredField(row[nullableIndex]) : false,
                defaultValue: defaultIndex !== -1 && row[defaultIndex] ? row[defaultIndex].toString().trim() : '',
                identity: identityIndex !== -1 && row[identityIndex] ? row[identityIndex].toString().toLowerCase().includes('是') : false,
                sequence: seqIndex !== -1 && row[seqIndex] ? parseInt(row[seqIndex]) : i,
                mapped: false
            };
            fields.push(field);
        }
    }

    // 保存数据
    if (tableType === 'A') {
        currentMapping.aTable = {
            name: `表A_${new Date().toLocaleDateString()}`,
            fields: fields
        };
        updateTableInfo('A', fields);
    } else {
        currentMapping.bTable = {
            name: `表B_${new Date().toLocaleDateString()}`,
            fields: fields
        };
        updateTableInfo('B', fields);
    }

    // 标记数据已更改
    markDataChanged();

    // 检查是否可以开始映射
    checkMappingReady();

    // 保存到localStorage
    saveCurrentMapping();

    showMessage(`${tableType}表数据导入成功，共${fields.length}个字段`, 'success');
}

// 更新表信息显示
function updateTableInfo(tableType, fields) {
    const infoDiv = document.getElementById(`${tableType.toLowerCase()}TableInfo`);
    const nameSpan = document.getElementById(`${tableType.toLowerCase()}TableName`);
    const countSpan = document.getElementById(`${tableType.toLowerCase()}FieldCount`);

    infoDiv.classList.remove('d-none');
    nameSpan.textContent = currentMapping[`${tableType.toLowerCase()}Table`].name;
    countSpan.textContent = fields.length;
}

// 检查是否可以开始映射
function checkMappingReady() {
    const startBtn = document.getElementById('startMappingBtn');
    if (currentMapping.aTable.fields.length > 0 && currentMapping.bTable.fields.length > 0) {
        startBtn.disabled = false;
        // 自动匹配相同字段名
        autoMatchFields();

        // 如果已经在映射界面，立即显示连线
        if (document.getElementById('mapping-tab').classList.contains('active')) {
            setTimeout(() => {
                if (typeof d3 !== 'undefined') {
                    drawConnectionsD3();
                } else {
                    drawConnections();
                }
            }, 100);
        }
    }
}

// 自动匹配字段
function autoMatchFields() {
    if (!currentMapping.aTable.fields.length || !currentMapping.bTable.fields.length) {
        showMessage('请先导入源表和目标表的结构', 'warning');
        return;
    }

    let matchCount = 0;

    // 清除现有映射
    currentMapping.mappings = [];
    currentMapping.aTable.fields.forEach(f => f.mapped = false);
    currentMapping.bTable.fields.forEach(f => f.mapped = false);

    // 按字段名匹配（忽略大小写和下划线差异）
    currentMapping.aTable.fields.forEach(aField => {
        const aFieldName = aField.name.toLowerCase().replace(/[_\s]/g, '');

        const matchingBField = currentMapping.bTable.fields.find(bField => {
            if (bField.mapped) return false;

            const bFieldName = bField.name.toLowerCase().replace(/[_\s]/g, '');

            // 完全匹配
            if (aFieldName === bFieldName) return true;

            // 包含匹配
            if (aFieldName.includes(bFieldName) || bFieldName.includes(aFieldName)) return true;

            return false;
        });

        if (matchingBField) {
            currentMapping.mappings.push({
                aField: aField.name,
                bField: matchingBField.name
            });
            aField.mapped = true;
            matchingBField.mapped = true;
            matchCount++;
        }
    });

    // 刷新显示
    if (document.getElementById('mapping-tab').classList.contains('active')) {
        if (typeof d3 !== 'undefined') {
            displayFieldsD3();
        } else {
            displayFields();
            setupFieldDragAndDrop();
            drawConnections();
        }
    } else {
        // 如果在表格视图，刷新表格显示
        displayFieldsTable();
        renderSourceFieldsList();
    }

    // 保存到localStorage
    saveCurrentMapping();

    showMessage(`自动匹配完成，共匹配${matchCount}个字段`, 'success');
}

// 切换到映射界面
function switchToMapping() {
    console.log('switchToMapping函数被调用');

    const mappingTab = document.getElementById('mapping-tab');
    console.log('找到mapping-tab元素:', mappingTab);

    if (!mappingTab) {
        console.error('未找到mapping-tab元素');
        showMessage('无法切换到字段映射页面', 'error');
        return;
    }

    try {
        const tab = new bootstrap.Tab(mappingTab);
        console.log('创建Bootstrap Tab对象成功');
        tab.show();
        console.log('Tab.show()调用完成');

        // 等待标签页切换完成后再显示字段
        mappingTab.addEventListener('shown.bs.tab', function () {
            console.log('Tab切换事件触发');
            // 使用表格视图显示字段
            displayFieldsTable();
            renderSourceFieldsList();

            console.log('表格字段映射已加载');
        }, { once: true }); // 只执行一次
    } catch (error) {
        console.error('创建或显示Tab时出错:', error);
        showMessage('切换到字段映射页面失败', 'error');
    }
}

// 目标表字段筛选
function filterBTableFieldsD3(filterType) {
    // 根据筛选条件更新filteredBFields
    switch (filterType) {
        case 'matched':
            filteredBFields = currentMapping.bTable.fields.filter(field => field.mapped);
            break;
        case 'unmatched':
            filteredBFields = currentMapping.bTable.fields.filter(field => !field.mapped);
            break;
        default:
            filteredBFields = [...currentMapping.bTable.fields];
    }

    // 添加tableType属性
    filteredBFields.forEach(field => {
        field.tableType = 'B';
    });

    // 重新渲染D3字段
    initializeD3Fields();
}

// 源表字段搜索
function filterATableFieldsD3(searchText) {
    if (!searchText.trim()) {
        filteredAFields = [...currentMapping.aTable.fields];
    } else {
        const searchLower = searchText.toLowerCase();

        filteredAFields = currentMapping.aTable.fields.filter(field => {
            const nameMatch = field.name.toLowerCase().includes(searchLower);
            const commentMatch = field.comment && field.comment.toLowerCase().includes(searchLower);

            // 简单的拼音首字母匹配
            const pinyinMatch = getPinyinInitial(field.name).toLowerCase().includes(searchLower);

            return nameMatch || commentMatch || pinyinMatch;
        });
    }

    // 添加tableType属性
    filteredAFields.forEach(field => {
        field.tableType = 'A';
    });

    // 重新渲染D3字段
    initializeD3Fields();
}


// 计算字段名相似度
function calculateFieldSimilarity(fieldAName, fieldBName) {
    const nameA = fieldAName.toLowerCase();
    const nameB = fieldBName.toLowerCase();

    // 完全匹配
    if (nameA === nameB) return 100;

    // 包含关系
    if (nameA.includes(nameB) || nameB.includes(nameA)) return 80;

    // 计算公共前缀/后缀
    let commonStart = 0;
    while (commonStart < Math.min(nameA.length, nameB.length) &&
           nameA[commonStart] === nameB[commonStart]) {
        commonStart++;
    }

    let commonEnd = 0;
    while (commonEnd < Math.min(nameA.length, nameB.length) &&
           nameA[nameA.length - 1 - commonEnd] === nameB[nameB.length - 1 - commonEnd]) {
        commonEnd++;
    }

    const commonRatio = (commonStart + commonEnd) / Math.max(nameA.length, nameB.length);

    // 关键词匹配
    const keywords = ['id', 'name', 'time', 'date', 'type', 'status', 'code', 'value', 'num', 'count'];
    let keywordScore = 0;
    keywords.forEach(keyword => {
        if (nameA.includes(keyword) && nameB.includes(keyword)) {
            keywordScore += 10;
        }
    });

    return Math.round(commonRatio * 50 + keywordScore);
}

// 智能排序源表字段
function smartSortAFields(targetBField) {
    if (!targetBField) {
        // 如果没有选中目标表字段，按默认顺序
        filteredAFields.sort((a, b) => {
            // 已匹配字段优先
            if (a.mapped && !b.mapped) return -1;
            if (!a.mapped && b.mapped) return 1;
            // 都匹配或都未匹配时，按字母顺序
            return a.name.localeCompare(b.name);
        });
    } else {
        // 根据与目标B字段的相似度排序
        filteredAFields.sort((a, b) => {
            // 已匹配字段优先
            if (a.mapped && !b.mapped) return -1;
            if (!a.mapped && b.mapped) return 1;

            // 都匹配或都未匹配时，按相似度排序
            const similarityA = calculateFieldSimilarity(a.name, targetBField.name);
            const similarityB = calculateFieldSimilarity(b.name, targetBField.name);

            if (similarityA !== similarityB) {
                return similarityB - similarityA; // 相似度高的在前
            }

            // 相似度相同时，按字母顺序
            return a.name.localeCompare(b.name);
        });
    }
}

// 显示字段 - 根据当前选择的视图模式
function displayFields() {
    // 使用表格布局显示字段映射
    displayFieldsTable();
}

// G6桑基图显示字段
function displayFieldsG6() {
    if (!currentMapping.aTable || !currentMapping.bTable) return;

    // 重置过滤器
    filteredAFields = [...currentMapping.aTable.fields];
    filteredBFields = [...currentMapping.bTable.fields];

    // 添加tableType属性到字段对象
    filteredAFields.forEach(field => {
        field.tableType = 'A';
    });
    filteredBFields.forEach(field => {
        field.tableType = 'B';
    });

    // 智能排序源表字段
    smartSortAFields();

    // 转换数据为G6桑基图格式
    convertToSankeyData();

    // 初始化或更新桑基图
    if (!sankeyGraph) {
        initSankeyGraph();
    } else {
        updateSankeyGraph();
    }

    // 侧边栏字段列表已移除，现在所有字段信息都在图表中显示

    // 添加窗口大小变化监听
    if (!window.g6ResizeListenerAdded) {
        window.addEventListener('resize', function() {
            if (sankeyGraph && currentMapping.mappings.length > 0) {
                setTimeout(() => {
                    sankeyGraph.changeSize(sankeyGraph.getWidth(), sankeyGraph.getHeight());
                    sankeyGraph.fitView();
                }, 100);
            }
        });
        window.g6ResizeListenerAdded = true;
    }
}

// 转换数据为G6桑基图格式 - 适应新的节点尺寸
function convertToSankeyData() {
    sankeyData.nodes = [];
    sankeyData.edges = [];

    // 计算节点间距，根据注释数量调整
    function getNodeHeight(field) {
        return field.comment ? 70 : 45;
    }

    // 计算目标表字段的累积Y坐标
    let bYPosition = 30;
    filteredBFields.forEach((field, index) => {
        const nodeHeight = getNodeHeight(field);
        sankeyData.nodes.push({
            id: `B-${field.name}`,
            name: field.name,
            type: 'field',
            tableType: 'B',
            x: 50,
            y: bYPosition,
            originalData: field
        });
        bYPosition += nodeHeight + 10; // 节点间间距
    });

    // 计算源表字段的累积Y坐标
    let aYPosition = 30;
    filteredAFields.forEach((field, index) => {
        const nodeHeight = getNodeHeight(field);
        sankeyData.nodes.push({
            id: `A-${field.name}`,
            name: field.name,
            type: 'field',
            tableType: 'A',
            x: 550,
            y: aYPosition,
            originalData: field
        });
        aYPosition += nodeHeight + 10; // 节点间间距
    });

    // 添加映射关系边
    currentMapping.mappings.forEach(mapping => {
        const sourceId = `B-${mapping.bField}`;
        const targetId = `A-${mapping.aField}`;

        sankeyData.edges.push({
            id: `${sourceId}-${targetId}`,
            source: sourceId,
            target: targetId,
            type: 'mapping',
            originalData: mapping
        });
    });
}

// 初始化G6桑基图
function initSankeyGraph() {
    const container = document.getElementById('g6SankeyContainer');
    if (!container) return;

    const width = container.clientWidth;
    const height = container.clientHeight;

    // 注册自定义节点 - 增强版显示更多字段信息和端点
    G6.registerNode('field-node', {
        draw(cfg, group) {
            const { name, tableType, originalData } = cfg;
            const isRequired = originalData?.required || false;
            const isMapped = originalData?.mapped || false;
            const comment = originalData?.comment || '';

            // 根据是否有注释调整节点高度
            const nodeHeight = comment ? 65 : 40;
            const nodeWidth = 160;

            // 节点矩形背景
            const rect = group.addShape('rect', {
                attrs: {
                    x: 0,
                    y: 0,
                    width: nodeWidth,
                    height: nodeHeight,
                    radius: 6,
                    fill: isMapped ? '#e8f5e8' : '#ffffff',
                    stroke: isMapped ? '#28a745' : '#dee2e6',
                    strokeWidth: isMapped ? 2 : 1,
                    cursor: 'pointer',
                    shadowColor: 'rgba(0,0,0,0.1)',
                    shadowBlur: isMapped ? 8 : 4,
                    shadowOffsetX: 0,
                    shadowOffsetY: 2
                },
                name: 'field-node-rect'
            });

            // 表类型标签背景
            const tableLabelBg = group.addShape('rect', {
                attrs: {
                    x: 0,
                    y: 0,
                    width: 30,
                    height: 16,
                    radius: '6 0 6 0',
                    fill: tableType === 'A' ? '#007bff' : '#28a745',
                    cursor: 'pointer'
                },
                name: 'table-label-bg'
            });

            // 表类型标签文字
            group.addShape('text', {
                attrs: {
                    x: 15,
                    y: 11,
                    text: tableType,
                    fontSize: 10,
                    fontWeight: 'bold',
                    fill: '#ffffff',
                    textAlign: 'center',
                    cursor: 'pointer'
                },
                name: 'table-label'
            });

            // 必填标记
            if (isRequired) {
                group.addShape('text', {
                    attrs: {
                        x: 38,
                        y: 12,
                        text: '*',
                        fontSize: 14,
                        fill: '#dc3545',
                        fontWeight: 'bold',
                        cursor: 'pointer'
                    },
                    name: 'required-mark'
                });
            }

            // 字段名
            group.addShape('text', {
                attrs: {
                    x: isRequired ? 50 : 38,
                    y: 16,
                    text: name.length > 15 ? name.substring(0, 15) + '...' : name,
                    fontSize: 13,
                    fontWeight: '600',
                    fill: '#2c3e50',
                    cursor: 'pointer'
                },
                name: 'field-name'
            });

            // 字段类型
            if (originalData?.type) {
                const typeText = originalData.type.length > 20 ? originalData.type.substring(0, 20) + '...' : originalData.type;
                group.addShape('rect', {
                    attrs: {
                        x: 38,
                        y: comment ? 25 : 24,
                        width: typeText.length * 7 + 8,
                        height: 16,
                        radius: 3,
                        fill: '#f8f9fa',
                        stroke: '#e9ecef',
                        cursor: 'pointer'
                    },
                    name: 'type-bg'
                });

                group.addShape('text', {
                    attrs: {
                        x: 42,
                        y: comment ? 36 : 35,
                        text: typeText,
                        fontSize: 10,
                        fill: '#6c757d',
                        fontFamily: 'monospace',
                        cursor: 'pointer'
                    },
                    name: 'field-type'
                });
            }

            // 字段注释
            if (comment) {
                const commentText = comment.length > 25 ? comment.substring(0, 25) + '...' : comment;
                group.addShape('text', {
                    attrs: {
                        x: 38,
                        y: 52,
                        text: commentText,
                        fontSize: 10,
                        fill: '#868e96',
                        fontStyle: 'italic',
                        cursor: 'pointer'
                    },
                    name: 'field-comment'
                });
            }

            // 增强的连接点 - 更大更明显
            if (tableType === 'B') {
                // 右侧连接点 - 目标表字段右侧
                group.addShape('circle', {
                    attrs: {
                        x: nodeWidth + 6,
                        y: nodeHeight / 2,
                        r: 8,
                        fill: isMapped ? '#28a745' : '#6c757d',
                        stroke: '#ffffff',
                        strokeWidth: 3,
                        cursor: 'crosshair',
                        shadowColor: 'rgba(0,0,0,0.3)',
                        shadowBlur: 6,
                        zIndex: 10
                    },
                    name: 'connection-point-right'
                });

                // 悬停时的连接点外圈
                group.addShape('circle', {
                    attrs: {
                        x: nodeWidth + 6,
                        y: nodeHeight / 2,
                        r: 10,
                        fill: 'transparent',
                        stroke: isMapped ? '#28a745' : '#007bff',
                        strokeWidth: 2,
                        cursor: 'crosshair',
                        opacity: 0,
                        zIndex: 9
                    },
                    name: 'connection-point-right-hover'
                });
            } else {
                // 左侧连接点 - 源表字段左侧
                group.addShape('circle', {
                    attrs: {
                        x: -6,
                        y: nodeHeight / 2,
                        r: 8,
                        fill: isMapped ? '#28a745' : '#6c757d',
                        stroke: '#ffffff',
                        strokeWidth: 3,
                        cursor: 'crosshair',
                        shadowColor: 'rgba(0,0,0,0.3)',
                        shadowBlur: 6,
                        zIndex: 10
                    },
                    name: 'connection-point-left'
                });

                // 悬停时的连接点外圈
                group.addShape('circle', {
                    attrs: {
                        x: -6,
                        y: nodeHeight / 2,
                        r: 10,
                        fill: 'transparent',
                        stroke: isMapped ? '#28a745' : '#ff6b35',
                        strokeWidth: 2,
                        cursor: 'crosshair',
                        opacity: 0,
                        zIndex: 9
                    },
                    name: 'connection-point-left-hover'
                });
            }

            // 映射状态指示器
            if (isMapped) {
                group.addShape('text', {
                    attrs: {
                        x: nodeWidth - 20,
                        y: 12,
                        text: '✓',
                        fontSize: 12,
                        fill: '#28a745',
                        fontWeight: 'bold',
                        cursor: 'pointer'
                    },
                    name: 'mapped-indicator'
                });
            }

            return rect;
        },

        update(cfg, node) {
            const group = node.getContainer();
            const rect = group.find(elem => elem.get('name') === 'field-node-rect');
            const { originalData } = cfg;
            const isMapped = originalData?.mapped || false;
            const tableType = cfg.tableType;

            // 更新节点背景
            rect.attr({
                fill: isMapped ? '#e8f5e8' : '#ffffff',
                stroke: isMapped ? '#28a745' : '#dee2e6',
                strokeWidth: isMapped ? 2 : 1
            });

            // 更新连接点颜色
            if (tableType === 'B') {
                const connectionPoint = group.find(elem => elem.get('name') === 'connection-point-right');
                const hoverPoint = group.find(elem => elem.get('name') === 'connection-point-right-hover');
                if (connectionPoint) {
                    connectionPoint.attr('fill', isMapped ? '#28a745' : '#6c757d');
                }
                if (hoverPoint) {
                    hoverPoint.attr('stroke', isMapped ? '#28a745' : '#007bff');
                }
            } else {
                const connectionPoint = group.find(elem => elem.get('name') === 'connection-point-left');
                const hoverPoint = group.find(elem => elem.get('name') === 'connection-point-left-hover');
                if (connectionPoint) {
                    connectionPoint.attr('fill', isMapped ? '#28a745' : '#6c757d');
                }
                if (hoverPoint) {
                    hoverPoint.attr('stroke', isMapped ? '#28a745' : '#ff6b35');
                }
            }
        },

        // 添加鼠标悬停事件处理
        setState(name, value, node) {
            const group = node.getContainer();
            const tableType = node.getModel().tableType;

            if (name === 'hover' && value) {
                // 显示悬停效果
                if (tableType === 'B') {
                    const hoverPoint = group.find(elem => elem.get('name') === 'connection-point-right-hover');
                    if (hoverPoint) {
                        hoverPoint.attr('opacity', 1);
                    }
                } else {
                    const hoverPoint = group.find(elem => elem.get('name') === 'connection-point-left-hover');
                    if (hoverPoint) {
                        hoverPoint.attr('opacity', 1);
                    }
                }
            } else if (name === 'hover' && !value) {
                // 隐藏悬停效果
                if (tableType === 'B') {
                    const hoverPoint = group.find(elem => elem.get('name') === 'connection-point-right-hover');
                    if (hoverPoint) {
                        hoverPoint.attr('opacity', 0);
                    }
                } else {
                    const hoverPoint = group.find(elem => elem.get('name') === 'connection-point-left-hover');
                    if (hoverPoint) {
                        hoverPoint.attr('opacity', 0);
                    }
                }
            }
        }
    });

    // 创建图实例 - 使用固定布局
    sankeyGraph = new G6.Graph({
        container: 'g6SankeyContainer',
        width: width,
        height: height,
        enabledDrag: true,
        modes: {
            default: [
                'drag-canvas',
                'zoom-canvas',
                {
                    type: 'drag-node',
                    enableDelegate: false,
                    onlyChangeData: false
                }
            ]
        },
        defaultNode: {
            type: 'field-node',
            size: [120, 40]
        },
        defaultEdge: {
            type: 'polyline',
            style: {
                stroke: '#666',
                strokeWidth: 1,
                strokeOpacity: 0.8,
                lineDash: [4, 2],
                endArrow: {
                    path: 'M 0,0 L 6,-3 L 6,3 Z',
                    fill: '#666'
                }
            }
        },
        // 节点状态样式
        nodeStateStyles: {
            selected: {
                shadowColor: '#2196f3',
                shadowBlur: 12,
                lineWidth: 3,
                stroke: '#2196f3'
            },
            hover: {
                shadowColor: '#2196f3',
                shadowBlur: 8
            },
            related: {
                shadowColor: '#667eea',
                shadowBlur: 6,
                lineWidth: 2,
                stroke: '#667eea'
            },
            dragging: {
                opacity: 0.7,
                shadowColor: '#ff6b35',
                shadowBlur: 10
            }
        },
        // 边状态样式
        edgeStateStyles: {
            selected: {
                stroke: '#dc3545',
                lineWidth: 2,
                lineDash: [4, 2],
                shadowColor: 'rgba(220, 53, 69, 0.6)',
                shadowBlur: 4
            },
            hover: {
                stroke: '#333',
                lineWidth: 2,
                shadowColor: 'rgba(0, 0, 0, 0.3)',
                shadowBlur: 4
            },
            'table-selected': {
                stroke: '#dc3545',
                lineWidth: 1.5,
                lineDash: [3, 2],
                opacity: 1,
                shadowColor: 'rgba(220, 53, 69, 0.6)',
                shadowBlur: 4
            }
        },
        layout: false, // 禁用自动布局，使用手动设置的坐标
        animate: false,
        fitView: false
    });

    // 绑定事件
    setupG6Events();

    // 渲染数据
    sankeyGraph.data(sankeyData);
    sankeyGraph.render();
}

// 更新桑基图
function updateSankeyGraph() {
    if (!sankeyGraph) return;

    sankeyGraph.data(sankeyData);
    sankeyGraph.refresh();
}

// 设置G6事件处理
function setupG6Events() {
    if (!sankeyGraph) return;

    // 节点点击事件
    sankeyGraph.on('node:click', (evt) => {
        const { item } = evt;
        const nodeData = item.getModel();

        // 设置选中的表
        setSelectedTable(nodeData.tableType);

        // 高亮节点
        sankeyGraph.getNodes().forEach(node => {
            sankeyGraph.clearItemStates(node);
        });
        sankeyGraph.setItemState(item, 'selected', true);

        // 高亮相关的边
        highlightRelatedEdges(nodeData.id);

        // 更新侧边栏选中状态
        updateFieldListSelection(nodeData);

        console.log('选中节点:', nodeData.name, '表类型:', nodeData.tableType);
    });

    // 边点击事件 - 删除连线
    sankeyGraph.on('edge:click', (evt) => {
        const { item } = evt;
        const edgeData = item.getModel();

        // 高亮选中的边
        sankeyGraph.getEdges().forEach(edge => {
            sankeyGraph.clearItemStates(edge);
        });
        sankeyGraph.setItemState(item, 'selected', true);

        // 删除映射
        if (confirm(`确定要删除映射 "${edgeData.originalData.bField} → ${edgeData.originalData.aField}" 吗？`)) {
            deleteMappingByEdge(edgeData.originalData);
        }
    });

    // 边悬停事件
    sankeyGraph.on('edge:mouseenter', (evt) => {
        const { item } = evt;
        sankeyGraph.setItemState(item, 'hover', true);

        // 高亮相关的节点
        const edgeData = item.getModel();
        const sourceNode = sankeyGraph.findById(edgeData.source);
        const targetNode = sankeyGraph.findById(edgeData.target);

        if (sourceNode) sankeyGraph.setItemState(sourceNode, 'related', true);
        if (targetNode) sankeyGraph.setItemState(targetNode, 'related', true);
    });

    sankeyGraph.on('edge:mouseleave', (evt) => {
        const { item } = evt;
        sankeyGraph.clearItemStates(item);

        // 清除相关节点的高亮
        sankeyGraph.getNodes().forEach(node => {
            sankeyGraph.clearItemStates(node, 'related');
        });
    });

    // 节点悬停事件 - 显示连接点
    sankeyGraph.on('node:mouseenter', (evt) => {
        const { item } = evt;
        sankeyGraph.setItemState(item, 'hover', true);
    });

    sankeyGraph.on('node:mouseleave', (evt) => {
        const { item } = evt;
        sankeyGraph.clearItemStates(item, 'hover');
    });

    // 画布点击事件（取消选择）
    sankeyGraph.on('canvas:click', () => {
        setSelectedTable(null);
        sankeyGraph.getNodes().forEach(node => {
            sankeyGraph.clearItemStates(node);
        });
        sankeyGraph.getEdges().forEach(edge => {
            sankeyGraph.clearItemStates(edge);
        });

        // 清除侧边栏选中状态
        clearFieldListSelection();
    });

    // 增强的拖拽事件
    let draggedNode = null;
    let dragStartPoint = null;

    // 拖拽开始
    sankeyGraph.on('node:dragstart', (evt) => {
        const { item, x, y } = evt;
        draggedNode = item.getModel();
        dragStartPoint = { x, y };

        console.log('开始拖拽:', draggedNode.name, draggedNode.tableType);

        // 设置拖拽状态
        sankeyGraph.setItemState(item, 'dragging', true);
    });

    // 拖拽过程
    sankeyGraph.on('node:drag', (evt) => {
        // 可以在这里添加拖拽过程中的视觉效果
    });

    // 拖拽结束 - 创建连接
    sankeyGraph.on('node:dragend', (evt) => {
        if (!draggedNode) return;

        const { x, y, target } = evt;
        const dragEndPoint = { x, y };

        // 清除拖拽状态
        const draggedItem = sankeyGraph.findById(draggedNode.id);
        if (draggedItem) {
            sankeyGraph.clearItemStates(draggedItem, 'dragging');
        }

        console.log('拖拽结束，目标:', target);

        // 检查是否拖拽到另一个节点上
        if (target && target.getType && target.getType() === 'node') {
            const targetNode = target.getModel();

            // 确保不是同一个节点且不是同一张表
            if (draggedNode.id !== targetNode.id && draggedNode.tableType !== targetNode.tableType) {
                console.log('创建映射:', draggedNode.name, '→', targetNode.name);
                createMappingFromNodes(draggedNode, targetNode);
            } else {
                console.log('无效的拖拽目标 - 同表或同一节点');
            }
        } else {
            // 检查是否拖拽到连接点附近
            const targetField = findNodeAtPosition(dragEndPoint);
            if (targetField && targetField.tableType !== draggedNode.tableType) {
                console.log('通过位置检测创建映射:', draggedNode.name, '→', targetField.name);
                createMappingFromNodes(draggedNode, targetField);
            } else {
                console.log('没有找到有效的目标节点');
            }
        }

        // 重置状态
        draggedNode = null;
        dragStartPoint = null;
    });
}

// 根据位置查找节点
function findNodeAtPosition(point) {
    const nodes = sankeyGraph.getNodes();

    for (let node of nodes) {
        const model = node.getModel();
        const bbox = node.getBBox();

        // 检查点是否在节点的连接点附近
        const connectionPointX = model.tableType === 'B' ?
            model.x + 166 : model.x - 6; // 考虑连接点位置
        const connectionPointY = model.y + (model.originalData?.comment ? 32.5 : 20);

        const distance = Math.sqrt(
            Math.pow(point.x - connectionPointX, 2) +
            Math.pow(point.y - connectionPointY, 2)
        );

        // 如果距离连接点15像素内，认为目标节点
        if (distance < 15) {
            return model;
        }
    }

    return null;
}

// 高亮相关的边
function highlightRelatedEdges(nodeId) {
    sankeyGraph.getEdges().forEach(edge => {
        const edgeData = edge.getModel();
        const isRelated = edgeData.source === nodeId || edgeData.target === nodeId;

        if (isRelated) {
            sankeyGraph.setItemState(edge, 'highlighted', true);
        } else {
            sankeyGraph.clearItemStates(edge);
        }
    });
}

// 从节点创建映射
function createMappingFromNodes(sourceNode, targetNode) {
    let aFieldName, bFieldName;

    if (sourceNode.tableType === 'A' && targetNode.tableType === 'B') {
        aFieldName = sourceNode.name;
        bFieldName = targetNode.name;
    } else if (sourceNode.tableType === 'B' && targetNode.tableType === 'A') {
        aFieldName = targetNode.name;
        bFieldName = sourceNode.name;
    } else {
        return;
    }

    // 创建映射
    createMapping(aFieldName, bFieldName);
}

// 通过边删除映射
function deleteMappingByEdge(mapping) {
    const index = currentMapping.mappings.findIndex(m =>
        m.aField === mapping.aField && m.bField === mapping.bField
    );

    if (index > -1) {
        currentMapping.mappings.splice(index, 1);

        // 更新字段状态
        const aField = currentMapping.aTable.fields.find(f => f.name === mapping.aField);
        const bField = currentMapping.bTable.fields.find(f => f.name === mapping.bField);

        if (aField) aField.mapped = false;
        if (bField) bField.mapped = false;

        // 标记数据已更改
        markDataChanged();

        // 重新渲染
        displayFieldsG6();
        showMessage(`已删除映射: ${mapping.bField} → ${mapping.aField}`, 'success');
    }
}

// 更新侧边栏字段列表
function updateFieldListPanels() {
    updateFieldList('bTableFieldList', filteredBFields, 'B');
    updateFieldList('aTableFieldList', filteredAFields, 'A');
}

// 更新字段列表
function updateFieldList(containerId, fields, tableType) {
    const container = document.getElementById(containerId);
    if (!container) return;

    container.innerHTML = '';

    fields.forEach(field => {
        const fieldItem = document.createElement('div');
        fieldItem.className = 'field-info-item';
        fieldItem.dataset.fieldName = field.name;
        fieldItem.dataset.tableType = tableType;

        if (field.mapped) fieldItem.classList.add('mapped');
        if (field.required) fieldItem.classList.add('required');

        fieldItem.innerHTML = `
            <div class="field-info-header">
                <span class="field-info-name">
                    ${field.required ? '<span class="field-info-required">*</span>' : ''}${field.name}
                </span>
                <span class="field-info-type">${field.type || 'VARCHAR'}</span>
            </div>
            ${field.comment ? `<div class="field-info-comment">${field.comment}</div>` : ''}
            ${field.mapped ? '<div class="field-info-mapped">✓</div>' : ''}
        `;

        // 添加点击事件
        fieldItem.addEventListener('click', () => {
            // 高亮对应的节点
            const nodeId = `${tableType}-${field.name}`;
            const node = sankeyGraph.findById(nodeId);
            if (node) {
                // 触发节点点击事件
                sankeyGraph.emit('node:click', { item: node });
            }
        });

        container.appendChild(fieldItem);
    });
}

// 更新字段列表选中状态
function updateFieldListSelection(nodeData) {
    // 清除所有选中状态
    document.querySelectorAll('.field-info-item').forEach(item => {
        item.classList.remove('selected');
    });

    // 设置当前选中
    const selectedItem = document.querySelector(`.field-info-item[data-field-name="${nodeData.name}"][data-table-type="${nodeData.tableType}"]`);
    if (selectedItem) {
        selectedItem.classList.add('selected');
        selectedItem.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
}

// 清除字段列表选中状态
function clearFieldListSelection() {
    document.querySelectorAll('.field-info-item').forEach(item => {
        item.classList.remove('selected');
    });
}

// D3.js显示字段
function displayFieldsD3() {
    if (!currentMapping.aTable || !currentMapping.bTable) return;

    // 重置过滤器
    filteredAFields = [...currentMapping.aTable.fields];
    filteredBFields = [...currentMapping.bTable.fields];

    // 添加tableType属性到字段对象
    filteredAFields.forEach(field => {
        field.tableType = 'A';
    });
    filteredBFields.forEach(field => {
        field.tableType = 'B';
    });

    // 智能排序源表字段
    smartSortAFields();

    // 初始化D3字段显示
    initializeD3Fields();

    // 绘制连接线 - 增加延迟确保DOM完全渲染
    setTimeout(() => {
        drawConnectionsD3();
    }, 150);

    // 添加窗口大小变化监听
    if (!window.resizeListenerAdded) {
        window.addEventListener('resize', function() {
            if (typeof d3 !== 'undefined' && currentMapping.mappings.length > 0) {
                setTimeout(() => drawConnectionsD3(), 100);
            }
        });
        window.resizeListenerAdded = true;
    }
}

// 初始化D3字段显示 - 使用数据绑定
function initializeD3Fields() {
    // 确保filteredAFields和filteredBFields已初始化
    if (!filteredAFields || filteredAFields.length === 0) {
        filteredAFields = [...currentMapping.aTable.fields];
    }
    if (!filteredBFields || filteredBFields.length === 0) {
        filteredBFields = [...currentMapping.bTable.fields];
    }

    // 添加tableType属性
    filteredAFields.forEach(field => {
        field.tableType = 'A';
    });
    filteredBFields.forEach(field => {
        field.tableType = 'B';
    });

    // 创建目标表字段（左侧）
    const bFields = d3.select('#bTableFields')
        .selectAll('.d3-field')
        .data(filteredBFields, d => `B-${d.name}`);

    // 移除旧字段
    bFields.exit().remove();

    // 添加新字段
    const bFieldsEnter = bFields.enter()
        .append('div')
        .attr('class', d => `d3-field ${d.mapped ? 'mapped' : ''} ${d.required ? 'required' : ''}`)
        .attr('data-field-name', d => d.name)
        .attr('data-table-type', 'B')
        .attr('data-field-id', d => `B-${d.name}`)
        .style('cursor', 'grab')
        .each(function(d) {
            d.element = this; // 将DOM元素引用存储到数据中
            d.tableType = 'B';
        });

    // 目标表字段内容
    bFieldsEnter.append('div')
        .attr('class', 'd3-field-content')
        .html(d => {
            const required = d.required ? '<span class="d3-field-required">*</span>' : '';
            return `
                ${required}
                <span class="d3-field-name" title="${d.name}">${d.name}</span>
                <span class="d3-field-type">${d.type}</span>
                <span class="d3-field-comment">${d.comment || ''}</span>
            `;
        });

    // 创建源表字段（右侧）
    const aFields = d3.select('#aTableFields')
        .selectAll('.d3-field')
        .data(filteredAFields, d => `A-${d.name}`);

    // 移除旧字段
    aFields.exit().remove();

    // 添加新字段
    const aFieldsEnter = aFields.enter()
        .append('div')
        .attr('class', d => `d3-field ${d.mapped ? 'mapped' : ''} ${d.required ? 'required' : ''}`)
        .attr('data-field-name', d => d.name)
        .attr('data-table-type', 'A')
        .attr('data-field-id', d => `A-${d.name}`)
        .style('cursor', 'grab')
        .each(function(d) {
            d.element = this; // 将DOM元素引用存储到数据中
            d.tableType = 'A';
        });

    // 源表字段内容
    aFieldsEnter.append('div')
        .attr('class', 'd3-field-content')
        .html(d => {
            const required = d.required ? '<span class="d3-field-required">*</span>' : '';
            return `
                ${required}
                <span class="d3-field-name" title="${d.name}">${d.name}</span>
                <span class="d3-field-type">${d.type}</span>
                <span class="d3-field-comment">${d.comment || ''}</span>
            `;
        });

    // 合并新旧字段用于事件绑定
    const allBFields = bFieldsEnter.merge(bFields);
    const allAFields = aFieldsEnter.merge(aFields);
    const allFields = allBFields.merge(allAFields);

    // 设置拖拽事件
    setupD3DragAndDrop();

    // 添加双击编辑功能
    allFields.on('dblclick', function(event, d) {
        editField(d, d.tableType);
    });

    // 添加点击高亮功能
    allFields.on('click', function(event, d) {
        // 移除之前的高亮
        d3.selectAll('.d3-field').classed('selected', false);
        d3.selectAll('.d3-connection').classed('selected-field', false);

        // 高亮当前字段
        d3.select(this).classed('selected', true);

        // 设置选中的表
        setSelectedTable(d.tableType);

        // 高亮相关连线
        highlightConnectionsForField(d);

        // 如果是B表字段，重新排序A表字段
        if (d.tableType === 'B') {
            smartSortAFields(d);
            initializeD3Fields();
            setTimeout(() => {
                drawConnectionsD3();
                // 重新高亮连线
                highlightConnectionsForField(d);
            }, 100);
        }
    });

    // 字段渲染完成后，立即更新连线
    setTimeout(() => drawConnectionsD3(), 50);

    // 添加连线自动更新机制
    setupConnectionAutoUpdate();

    // 添加点击空白区域取消选择的事件
    setupClickOutsideHandler();
}

// 高亮字段相关的连线
function highlightConnectionsForField(fieldData) {
    // 清除之前的高亮
    d3.selectAll('.d3-connection').classed('selected-field', false);

    // 找到与该字段相关的所有连线
    const connections = d3.selectAll('.d3-connection');

    connections.each(function(d) {
        if (!d.aFieldData || !d.bFieldData) return;

        // 检查当前字段是否是连线的起点或终点
        if ((d.aFieldData.name === fieldData.name && d.aFieldData.tableType === fieldData.tableType) ||
            (d.bFieldData.name === fieldData.name && d.bFieldData.tableType === fieldData.tableType)) {
            d3.select(this).classed('selected-field', true);
        }
    });
}

// 设置连线自动更新机制
function setupConnectionAutoUpdate() {
    // 清除之前的观察器
    if (window.fieldObserver) {
        window.fieldObserver.disconnect();
    }

    // 创建MutationObserver来监控字段容器变化
    const aContainer = document.getElementById('aTableFields');
    const bContainer = document.getElementById('bTableFields');

    if (!aContainer || !bContainer) return;

    window.fieldObserver = new MutationObserver(function(mutations) {
        let shouldUpdateConnections = false;

        mutations.forEach(function(mutation) {
            if (mutation.type === 'childList' ||
                mutation.type === 'attributes' &&
                (mutation.attributeName === 'class' || mutation.attributeName === 'style')) {
                shouldUpdateConnections = true;
            }
        });

        if (shouldUpdateConnections) {
            // 延迟更新，确保DOM变化完成
            setTimeout(() => {
                drawConnectionsD3();
            }, 10);
        }
    });

    // 观察两个容器
    window.fieldObserver.observe(aContainer, {
        childList: true,
        subtree: true,
        attributes: true,
        attributeFilter: ['class', 'style']
    });

    window.fieldObserver.observe(bContainer, {
        childList: true,
        subtree: true,
        attributes: true,
        attributeFilter: ['class', 'style']
    });
}

// 拖拽结束处理函数
function handleDragEnd(fieldData, event) {
    const clientX = event.sourceEvent.clientX;
    const clientY = event.sourceEvent.clientY;

    const target = document.elementFromPoint(clientX, clientY);
    const targetField = target?.closest('.d3-field');

    if (targetField) {
        const targetType = targetField.dataset.tableType;
        const targetName = targetField.dataset.fieldName;

        fieldData.tableType = fieldData.tableType || 'A';

        if (fieldData.tableType !== targetType) {
            if (fieldData.tableType === 'A' && targetType === 'B') {
                createMapping(fieldData.name, targetName);
            } else if (fieldData.tableType === 'B' && targetType === 'A') {
                createMapping(targetName, fieldData.name);
            }
        } else {
            reorderFields(fieldData, targetField);
        }
    }
}

// 设置D3拖拽功能
function setupD3DragAndDrop() {
    // 应用拖拽到所有字段
    const fields = d3.selectAll('.d3-field');
    console.log('找到字段数量:', fields.size());

    setupDragForSelection(fields);
}

// 创建统一的拖拽行为
function createDragBehavior() {
    return d3.drag()
        .on('start', function(event, d) {
            // 确定表格类型
            d.tableType = d.tableType || (this.closest('#aTableFields') ? 'A' : 'B');

            console.log('拖拽开始:', d.name, d.tableType);

            d3.select(this).classed('dragging', true);
            this.style.opacity = '0.5';
            this.style.zIndex = '1000';

            // 防止事件冒泡
            event.sourceEvent.stopPropagation();
            event.sourceEvent.preventDefault();

            // 创建临时连接线
            createTempConnectionLine(d);
        })
        .on('drag', function(event, d) {
            // 更新临时连接线位置
            updateTempConnectionLine(event);

            // 防止默认行为
            event.sourceEvent.preventDefault();
        })
        .on('end', function(event, d) {
            console.log('拖拽结束:', d.name);

            d3.select(this).classed('dragging', false);
            this.style.opacity = '1';
            this.style.zIndex = '';

            // 移除临时连接线
            removeTempConnectionLine();

            // 防止事件冒泡
            event.sourceEvent.stopPropagation();
            event.sourceEvent.preventDefault();

            // 处理拖拽结束
            handleDragEnd(d, event);
        });
}

// 为D3选择集设置拖拽
function setupDragForSelection(selection) {
    selection.each(function(d) {
        // 确保每个字段都有tableType
        d.tableType = d.tableType || (this.closest('#aTableFields') ? 'A' : 'B');
    });

    selection.call(createDragBehavior());
}

// 创建临时连接线
function createTempConnectionLine(fieldData) {
    const svg = d3.select('#d3Connections');
    const sourceField = d3.select(`.d3-field[data-field-name="${fieldData.name}"][data-table-type="${fieldData.tableType}"]`);

    if (sourceField.empty()) return;

    const sourceRect = sourceField.node().getBoundingClientRect();
    const svgContainer = document.getElementById('d3Connections');
    const svgRect = svgContainer.getBoundingClientRect();

    // 获取SVG容器的实际宽度
    const svgWidth = svgRect.width;

    // 计算起点位置 - 延伸到对应的边界
    let startX, startY;
    if (fieldData.tableType === 'A') {
        // A表字段在右边，从右边界开始
        startX = svgWidth;
    } else {
        // B表字段在左边，从左边界开始
        startX = 0;
    }
    startY = sourceRect.top - svgRect.top + sourceRect.height / 2;

    console.log('创建临时连接线:', fieldData.name, startX, startY, 'SVG宽度:', svgWidth);

    svg.append('path')
        .attr('class', 'd3-temp-connection')
        .attr('id', 'tempConnection')
        .attr('d', `M${startX},${startY} L${startX},${startY}`);
}

// 更新临时连接线
function updateTempConnectionLine(event) {
    const svg = d3.select('#d3Connections');
    const container = svg.node().parentElement.getBoundingClientRect();
    const tempLine = svg.select('#tempConnection');

    if (tempLine.empty()) return;

    const currentPath = tempLine.attr('d');
    const startPoint = currentPath.split('M')[1].split('L')[0];
    const endX = event.sourceEvent.clientX - container.left;
    const endY = event.sourceEvent.clientY - container.top;

    // 解析起始点坐标
    const [startX, startY] = startPoint.split(',').map(Number);

    // 创建平滑的两折线临时路径
    const quarterX = startX + (endX - startX) * 0.25;
    const threeQuarterX = startX + (endX - startX) * 0.75;

    const path = `M${startX},${startY}
                  L${quarterX},${startY}
                  Q${(quarterX + threeQuarterX) / 2},${(startY + endY) / 2} ${threeQuarterX},${endY}
                  L${endX},${endY}`;

    tempLine.attr('d', path);
}

// 移除临时连接线
function removeTempConnectionLine() {
    d3.select('#tempConnection').remove();
}

// 同侧字段重排序
function reorderFields(sourceField, targetField) {
    const sourceType = sourceField.tableType;
    const targetType = targetField.dataset.tableType;

    if (sourceType !== targetType) return;

    const fields = sourceType === 'A' ? filteredAFields : filteredBFields;
    const sourceIndex = fields.findIndex(f => f.name === sourceField.name);
    const targetIndex = fields.findIndex(f => f.name === targetField.dataset.fieldName);

    if (sourceIndex !== -1 && targetIndex !== -1) {
        // 移动字段位置
        const [movedField] = fields.splice(sourceIndex, 1);
        fields.splice(targetIndex, 0, movedField);

        // 重新渲染 - 连线会通过数据绑定自动更新
        initializeD3Fields();
        // 不需要手动调用drawConnectionsD3()，因为initializeD3Fields已经处理
    }
}

// 绘制D3连接线 - 基于字段数据绑定
function drawConnectionsD3() {
    const svg = d3.select('#d3Connections');
    if (!svg.node()) return;

    const container = svg.node().parentElement.getBoundingClientRect();

    // 准备连线数据，基于当前筛选的字段数据
    const connectionData = currentMapping.mappings.map(mapping => {
        const aFieldData = filteredAFields.find(f => f.name === mapping.aField);
        const bFieldData = filteredBFields.find(f => f.name === mapping.bField);

        return {
            ...mapping,
            aFieldData: aFieldData,
            bFieldData: bFieldData,
            id: `${mapping.bField}-${mapping.aField}`
        };
    }).filter(conn => conn.aFieldData && conn.bFieldData);

    // 使用D3数据绑定更新连线
    const connections = svg.selectAll('.d3-connection')
        .data(connectionData, d => d.id);

    // 移除不存在的连线（带动画）
    connections.exit()
        .transition()
        .duration(200)
        .style('opacity', 0)
        .remove();

    // 添加新连线（带动画）
    const connectionsEnter = connections.enter()
        .append('path')
        .attr('class', 'd3-connection')
        .style('opacity', 0)
        .on('click', function(event, d) {
            event.stopPropagation();
            deleteMappingD3(d);
        });

    // 合并新连线和现有连线
    const connectionsUpdate = connectionsEnter.merge(connections);

    // 更新所有连线路径
    updateConnectionsPath(connectionsUpdate, container);

    // 根据选中的表设置连线样式
    updateConnectionStyles(connectionsUpdate);

    // 淡入动画
    connectionsUpdate
        .transition()
        .duration(200)
        .style('opacity', 1);
}

// 更新连线路径函数 - 基于字段数据绑定
function updateConnectionsPath(connections, container) {
    connections.each(function(d) {
        if (!d.aFieldData || !d.bFieldData) return;

        // 从字段数据中获取DOM元素
        const aElement = d.aFieldData.element;
        const bElement = d.bFieldData.element;

        if (!aElement || !bElement) return;

        const aRect = aElement.getBoundingClientRect();
        const bRect = bElement.getBoundingClientRect();

        // 获取映射容器的完整尺寸
        const mappingContainer = document.querySelector('.d3-mapping-container');
        const mappingRect = mappingContainer.getBoundingClientRect();
        const svgContainer = document.getElementById('d3Connections');
        const svgRect = svgContainer.getBoundingClientRect();

        // 计算SVG容器的实际可用宽度和高度
        const svgWidth = svgRect.width;
        const svgHeight = svgRect.height;

        // 计算左右边界在SVG坐标系中的位置
        // 左边界是SVG的左边，右边界是SVG的右边
        const leftBoundary = 0;
        const rightBoundary = svgWidth;

        // 计算字段在Y轴上的位置（相对于SVG容器）
        const startY = aRect.top - svgRect.top + aRect.height / 2;
        const endY = bRect.top - svgRect.top + bRect.height / 2;

        // 根据字段类型确定起点和终点
        let startX, endX;

        if (d.aFieldData.tableType === 'A') {
            // A表字段在右边，从右边界开始
            startX = rightBoundary;
            // B表字段在左边，到左边界结束
            endX = leftBoundary;
        } else {
            // B表字段在左边，从左边界开始
            startX = leftBoundary;
            // A表字段在右边，到右边界结束
            endX = rightBoundary;
        }

        // 创建平滑的两折线路径
        // 使用两个折点，让线条在水平方向延伸，然后平滑转折
        const quarterX = startX + (endX - startX) * 0.25;
        const threeQuarterX = startX + (endX - startX) * 0.75;

        // 创建平滑的两折线路径：从起点出发，先水平延伸一小段，然后斜向中间，再水平延伸到终点
        const path = `M${startX},${startY}
                      L${quarterX},${startY}
                      Q${(quarterX + threeQuarterX) / 2},${(startY + endY) / 2} ${threeQuarterX},${endY}
                      L${endX},${endY}`;

        d3.select(this)
            .attr('d', path)
            .attr('data-mapping', d.id)
            .attr('data-a-field', d.aFieldData.name)
            .attr('data-b-field', d.bFieldData.name)
            .attr('data-a-table', d.aFieldData.tableType)
            .attr('data-b-table', d.bFieldData.tableType);
    });
}

// 更新连线样式函数 - 根据选中的表设置高亮
function updateConnectionStyles(connections) {
    connections.each(function(d) {
        const connection = d3.select(this);

        // 清除所有表相关的高亮样式
        connection.classed('table-a-selected', false);
        connection.classed('table-b-selected', false);

        // 根据选中的表设置高亮
        if (selectedTable === 'A') {
            // 如果选中了A表，所有连线都高亮显示为红色细虚线
            connection.classed('table-a-selected', true);
        } else if (selectedTable === 'B') {
            // 如果选中了B表，所有连线都高亮显示为红色细虚线
            connection.classed('table-b-selected', true);
        }
    });
}

// 设置选中的表 - D3版本
function setSelectedTable(tableType) {
    selectedTable = tableType; // 'A', 'B', 或 null

    // 更新所有连线的样式
    const connections = d3.selectAll('.d3-connection');
    updateConnectionStyles(connections);

    console.log('选中表类型:', selectedTable);
}

// 设置点击空白区域取消选择的处理
function setupClickOutsideHandler() {
    // 为映射容器添加点击事件
    const mappingContainer = document.querySelector('.d3-mapping-container');
    if (mappingContainer) {
        mappingContainer.addEventListener('click', function(event) {
            // 如果点击的不是字段或连线，则取消选择
            const clickedField = event.target.closest('.d3-field');
            const clickedConnection = event.target.closest('.d3-connection');

            if (!clickedField && !clickedConnection) {
                // 取消表的选择
                setSelectedTable(null);

                // 移除所有字段的高亮
                d3.selectAll('.d3-field').classed('selected', false);

                // 移除所有连线的高亮
                d3.selectAll('.d3-connection').classed('selected-field', false);
            }
        });
    }
}

// D3删除映射
function deleteMappingD3(mapping) {
    if (confirm(`确定要删除映射 "${mapping.bField} → ${mapping.aField}" 吗？`)) {
        // 从映射数组中移除
        const index = currentMapping.mappings.findIndex(m => m.aField === mapping.aField && m.bField === mapping.bField);
        if (index > -1) {
            currentMapping.mappings.splice(index, 1);
        }

        // 更新字段状态
        const aField = currentMapping.aTable.fields.find(f => f.name === mapping.aField);
        const bField = currentMapping.bTable.fields.find(f => f.name === mapping.bField);

        if (aField) aField.mapped = false;
        if (bField) bField.mapped = false;

        // 标记数据已更改
        markDataChanged();

        // 重新渲染
        displayFieldsD3();
        showMessage('映射已删除', 'success');
    }
}

// 回退版本（如果D3未加载）
function displayFieldsLegacy() {
    const aContainer = document.getElementById('aTableFields');
    const bContainer = document.getElementById('bTableFields');

    aContainer.innerHTML = '';
    bContainer.innerHTML = '';

    // 重置过滤器
    filteredAFields = [...currentMapping.aTable.fields];
    filteredBFields = [...currentMapping.bTable.fields];

    // 智能排序源表字段
    smartSortAFields();

    // 显示B表字段（左侧，目标表）
    filteredBFields.forEach(field => {
        const fieldCard = createFieldCard(field, 'B');
        bContainer.appendChild(fieldCard);
    });

    // 显示A表字段（右侧，源表）
    filteredAFields.forEach(field => {
        const fieldCard = createFieldCard(field, 'A');
        aContainer.appendChild(fieldCard);
    });

    // 重置筛选器
    document.getElementById('bTableFilter').value = 'all';
    document.getElementById('aTableSearch').value = '';

    // 绘制连线
    setTimeout(() => {
        drawConnections();
    }, 100);
}

// 创建字段卡片
function createFieldCard(field, tableType) {
    const card = document.createElement('div');
    card.className = `field-item ${field.required ? 'required' : 'optional'} ${field.mapped ? 'mapped-field' : ''}`;
    card.dataset.fieldName = field.name;
    card.dataset.tableType = tableType;

    const requiredHtml = field.required ? '<span class="text-danger">*</span>' : '';

    // 一行显示：字段名、类型、注释
    card.style.position = 'relative';
    card.innerHTML = `
        <div class="field-content">
            <div class="field-name" title="${field.name}">
                ${requiredHtml}${field.name}
            </div>
            <div class="field-type">${field.type}</div>
            <div class="field-comment">${field.comment || ''}</div>
        </div>
        ${tableType === 'B' ? `
            <div class="connection-point left-connection" data-table-type="${tableType}" data-field-name="${field.name}"
                 onmousedown="startConnection(event, '${tableType}', '${field.name}')"></div>
        ` : `
            <div class="connection-point right-connection" data-table-type="${tableType}" data-field-name="${field.name}"
                 onmouseup="handleConnectionEnd(event)"></div>
        `}
        ${field.mapped ? '<div class="mapped-indicator">✓</div>' : ''}
    `;

    // 添加双击编辑功能
    card.addEventListener('dblclick', (e) => {
        if (!e.target.closest('.connection-point')) {
            editField(field, tableType);
        }
    });

    // B表字段点击时触发智能排序
    if (tableType === 'B') {
        card.addEventListener('click', (e) => {
            if (!e.target.closest('.connection-point')) {
                // 高亮当前选中的B表字段
                document.querySelectorAll('.field-item').forEach(item => {
                    item.classList.remove('selected-b-field');
                });
                card.classList.add('selected-b-field');

                // 重新排序并显示A表字段
                smartSortAFields(field);
                const aContainer = document.getElementById('aTableFields');
                aContainer.innerHTML = '';
                filteredAFields.forEach(fieldItem => {
                    const fieldCard = createFieldCard(fieldItem, 'A');
                    aContainer.appendChild(fieldCard);
                });

                // 重新绘制连接线
                setTimeout(() => {
                    drawConnections();
                }, 100);
            }
        });
    }

    return card;
}

// 开始连接拖拽
function startConnection(event, tableType, fieldName) {
    event.stopPropagation();

    isDragging = true;
    dragStartPoint = {
        tableType: tableType,
        fieldName: fieldName,
        element: event.target
    };

    // 高亮开始点
    event.target.classList.add('source');

    // 添加全局鼠标事件监听
    document.addEventListener('mousemove', handleConnectionDrag);
    document.addEventListener('mouseup', handleConnectionEnd);

    showMessage('拖拽到A表字段建立连接', 'info');
}

// 处理连接拖拽
function handleConnectionDrag(event) {
    if (!isDragging) return;

    const svg = document.getElementById('connectionSvg');
    if (!svg) return;

    // 移除临时连线
    if (tempConnection) {
        tempConnection.remove();
    }

    // 获取起始点坐标
    const startPoint = dragStartPoint.element.getBoundingClientRect();
    const containerRect = svg.getBoundingClientRect();

    const startX = startPoint.right - containerRect.left;
    const startY = startPoint.top - containerRect.top + startPoint.height / 2;

    // 创建临时连线
    tempConnection = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    tempConnection.setAttribute('class', 'connection-line');
    tempConnection.setAttribute('stroke', '#667eea');
    tempConnection.setAttribute('stroke-width', '2');
    tempConnection.setAttribute('fill', 'none');
    tempConnection.setAttribute('opacity', '0.6');
    tempConnection.setAttribute('stroke-dasharray', '5,5');

    // 计算鼠标位置
    const mouseX = event.clientX - containerRect.left;
    const mouseY = event.clientY - containerRect.top;

    // 创建贝塞尔曲线路径
    const midX = (startX + mouseX) / 2;
    const midY = Math.min(startY, mouseY) - 20;

    const d = `M ${startX} ${startY} Q ${midX} ${midY} ${mouseX} ${mouseY}`;
    tempConnection.setAttribute('d', d);

    svg.appendChild(tempConnection);
}

// 处理连接结束
function handleConnectionEnd(event) {
    if (!isDragging) return;

    event.preventDefault();
    event.stopPropagation();

    // 移除临时连线
    if (tempConnection) {
        tempConnection.remove();
        tempConnection = null;
    }

    // 移除开始点高亮
    if (dragStartPoint && dragStartPoint.element) {
        dragStartPoint.element.classList.remove('source');
    }

    // 检查是否拖拽到A表字段或连接点
    const target = document.elementFromPoint(event.clientX, event.clientY);
    const aFieldCard = target?.closest('.field-item[data-table-type="A"]');
    const aConnectionPoint = target?.closest('.connection-point[data-table-type="A"]');

    if (aFieldCard || aConnectionPoint) {
        const aFieldName = aFieldCard?.dataset.fieldName || aConnectionPoint?.dataset.fieldName;
        const bFieldName = dragStartPoint.fieldName;

        if (aFieldName && bFieldName) {
            // 创建映射
            createMapping(aFieldName, bFieldName);
        }
    }

    // 重置状态
    isDragging = false;
    dragStartPoint = null;
    dragEndPoint = null;

    // 移除全局事件监听
    document.removeEventListener('mousemove', handleConnectionDrag);
    document.removeEventListener('mouseup', handleConnectionEnd);
}

// 设置字段拖拽（现在主要使用连接点拖拽）
function setupFieldDragAndDrop() {
    // 连接点拖拽功能已在startConnection中实现
    console.log('可视化连接拖拽已初始化');
}

// 创建映射
function createMapping(aFieldName, bFieldName) {
    // 检查是否已存在映射
    const existingMapping = currentMapping.mappings.find(m => m.aField === aFieldName);
    if (existingMapping) {
        showMessage('该A表字段已映射到其他字段', 'warning');
        return;
    }

    // 添加映射
    currentMapping.mappings.push({
        aField: aFieldName,
        bField: bFieldName
    });

    // 标记数据已更改
    markDataChanged();

    // 更新字段状态
    const aField = currentMapping.aTable.fields.find(f => f.name === aFieldName);
    const bField = currentMapping.bTable.fields.find(f => f.name === bFieldName);

    if (aField) aField.mapped = true;
    if (bField) bField.mapped = true;

    // 刷新显示
    if (typeof G6 !== 'undefined') {
        displayFieldsG6();
    } else {
        displayFields();
        drawConnections();
    }

    // 自动保存
    autoSave();

    showMessage(`成功创建映射: ${bFieldName} → ${aFieldName}`, 'success');
}

// 清除所有映射
function clearAllMappings() {
    if (confirm('确定要清除所有映射关系吗？')) {
        currentMapping.mappings = [];

        // 重置字段映射状态
        currentMapping.aTable.fields.forEach(f => f.mapped = false);
        currentMapping.bTable.fields.forEach(f => f.mapped = false);

        // 标记数据已更改
        markDataChanged();

        if (typeof G6 !== 'undefined') {
            displayFieldsG6();
        } else {
            displayFields();
            setupFieldDragAndDrop();
            drawConnections();
        }

        // 重置过滤字段状态
        filteredAFields.forEach(f => {
            f.mapped = false;
            f.referenceCount = 0;
        });
        filteredBFields.forEach(f => {
            f.mapped = false;
        });

        // 如果在表格视图，刷新表格
        displayFieldsTable();
        renderSourceFieldsList();

        // 保存到localStorage
        saveCurrentMapping();

        showMessage('已清除所有映射关系', 'info');
    }
}

// 编辑字段
function editField(field, tableType) {
    const modal = new bootstrap.Modal(document.getElementById('editFieldModal'));

    document.getElementById('editFieldName').value = field.name;
    document.getElementById('editFieldComment').value = field.comment || '';
    document.getElementById('editFieldType').value = field.type || 'VARCHAR';
    document.getElementById('editFieldRequired').checked = field.required || false;

    // 保存编辑
    window.currentEditingField = { field, tableType };
    modal.show();
}

// 保存字段编辑
function saveFieldEdit() {
    const { field, tableType } = window.currentEditingField;

    field.comment = document.getElementById('editFieldComment').value;
    field.type = document.getElementById('editFieldType').value;
    field.required = document.getElementById('editFieldRequired').checked;

    // 标记数据已更改
    markDataChanged();

    // 刷新显示
    if (typeof G6 !== 'undefined') {
        displayFieldsG6();
    } else {
        displayFields();
        setupFieldDragAndDrop();
    }

    bootstrap.Modal.getInstance(document.getElementById('editFieldModal')).hide();
    showMessage('字段信息已更新', 'success');
}

// 批量应用注释
function applyComments(tableType, isMappingPanel = false) {
    const textareaId = isMappingPanel
        ? `${tableType.toLowerCase()}TableMappingComments`
        : `${tableType.toLowerCase()}TableComments`;
    const textarea = document.getElementById(textareaId);

    if (!textarea) {
        showMessage('找不到对应的文本框', 'warning');
        return;
    }

    const text = textarea.value.trim();

    if (!text) {
        showMessage('请输入字段说明内容', 'warning');
        return;
    }

    const lines = text.split('\n');
    let updatedCount = 0;

    lines.forEach(line => {
        const match = line.match(/^([^:：]+)[:：]\s*(.+)$/);
        if (match) {
            const fieldName = match[1].trim();
            const comment = match[2].trim();

            const table = tableType === 'A' ? currentMapping.aTable : currentMapping.bTable;
            const field = table.fields.find(f => f.name === fieldName);

            if (field) {
                field.comment = comment;
                updatedCount++;
            }
        }
    });

    if (updatedCount > 0) {
        showMessage(`成功更新${updatedCount}个字段的说明`, 'success');
        textarea.value = '';

        // 如果已经在映射界面，刷新显示
        if (document.getElementById('mapping-tab').classList.contains('active')) {
            if (typeof d3 !== 'undefined') {
                displayFieldsD3();
            } else {
                displayFields();
                setupFieldDragAndDrop();
            }
        }
    } else {
        showMessage('未找到匹配的字段，请检查字段名格式', 'warning');
    }
}

// 生成SQL
function generateSQL() {
    if (currentMapping.mappings.length === 0) {
        showMessage('请先创建字段映射关系', 'warning');
        return;
    }

    const sqlValues = generateValuesSQL();
    const sqlUpdate = generateUpdateSQL();
    const sqlMerge = generateMergeSQL();
    const sqlFull = generateFullSQL(sqlValues, sqlMerge);

    document.getElementById('sqlValues').textContent = sqlValues;
    document.getElementById('sqlUpdate').textContent = sqlUpdate;
    document.getElementById('sqlMerge').textContent = sqlMerge;

    // 添加完整SQL显示
    const sqlFullElement = document.getElementById('sqlFull');
    if (sqlFullElement) {
        sqlFullElement.textContent = sqlFull;
    }

    // 切换到SQL标签页
    const sqlTab = document.getElementById('sql-tab');
    const tab = new bootstrap.Tab(sqlTab);
    tab.show();

    showMessage('SQL生成成功', 'success');
}

// 格式化字段列表，每5个字段换行
function formatFieldList(fields) {
    let result = '';
    for (let i = 0; i < fields.length; i++) {
        if (i > 0) {
            result += ', ';
            if (i % 5 === 0) {
                result += '\n    ';
            }
        }
        result += fields[i];
    }
    return result;
}

// 格式化值列表，每5个值换行
function formatValueList(values) {
    let result = '';
    for (let i = 0; i < values.length; i++) {
        if (i > 0) {
            result += ', ';
            if (i % 5 === 0) {
                result += '\n    ';
            }
        }
        result += values[i];
    }
    return result;
}

// 生成VALUES格式的SQL
function generateValuesSQL() {
    // 获取所有目标表字段，按导入顺序
    const allBFields = currentMapping.bTable.fields;

    // 分离已匹配和未匹配的字段
    const matchedFields = [];
    const unmatchedFields = [];

    allBFields.forEach(field => {
        const mapping = currentMapping.mappings.find(m => m.bField === field.name);
        if (mapping) {
            matchedFields.push(field);
        } else {
            unmatchedFields.push(field);
        }
    });

    // 按目标表导入顺序重新排列：已匹配字段在前，未匹配字段在后
    const orderedFields = [...matchedFields, ...unmatchedFields];

    // 构建字段列表，每5个字段换行
    const fieldNames = orderedFields.map(field => field.name);
    const bFields = formatFieldList(fieldNames);

    // 构建值列表，保持与字段列表相同的顺序
    const aValueList = orderedFields.map(field => {
        const mapping = currentMapping.mappings.find(m => m.bField === field.name);
        if (mapping) {
            return generateFieldValueTemplate(field, mapping.aField);
        } else {
            // 未匹配的字段直接使用null
            return 'NULL';
        }
    });

    // 格式化值列表，每5个值换行
    const aValues = formatValueList(aValueList);

    return `(${bFields})\nVALUES (${aValues})`;
}

// 生成UPDATE格式的SQL
function generateUpdateSQL() {
    // 获取所有目标表字段，按导入顺序
    const allBFields = currentMapping.bTable.fields;

    // 分离已匹配和未匹配的字段
    const matchedFields = [];
    const unmatchedFields = [];

    allBFields.forEach(field => {
        const mapping = currentMapping.mappings.find(m => m.bField === field.name);
        if (mapping) {
            matchedFields.push(field);
        } else {
            unmatchedFields.push(field);
        }
    });

    // 按目标表导入顺序重新排列：已匹配字段在前，未匹配字段在后
    const orderedFields = [...matchedFields, ...unmatchedFields];

    // 构建UPDATE语句，每5个字段换行
    const updateClauses = orderedFields.map((field, index) => {
        const mapping = currentMapping.mappings.find(m => m.bField === field.name);
        let clause = '';
        if (mapping) {
            const valueTemplate = generateFieldValueTemplate(field, mapping.aField);
            clause = `${field.name}=${valueTemplate}`;
        } else {
            // 未匹配的字段直接使用null
            clause = `${field.name}=NULL`;
        }

        // 每5个字段换行
        if (index > 0 && index % 5 === 0) {
            return '\n' + clause;
        }
        return clause;
    });

    return updateClauses.join(',\n');
}

// 生成MERGE格式的SQL
function generateMergeSQL() {
    // 获取所有目标表字段，按导入顺序
    const allBFields = currentMapping.bTable.fields;

    // 分离已匹配和未匹配的字段
    const matchedFields = [];
    const unmatchedFields = [];

    allBFields.forEach(field => {
        const mapping = currentMapping.mappings.find(m => m.bField === field.name);
        if (mapping) {
            matchedFields.push(field);
        } else {
            unmatchedFields.push(field);
        }
    });

    // 按目标表导入顺序重新排列：已匹配字段在前，未匹配字段在后
    const orderedFields = [...matchedFields, ...unmatchedFields];

    // 构建MERGE语句，使用双括号格式，每5个字段换行
    const mergeClauses = orderedFields.map((field, index) => {
        const mapping = currentMapping.mappings.find(m => m.bField === field.name);
        let clause = '';
        if (mapping) {
            const aFieldExists = currentMapping.aTable.fields.some(f => f.name === mapping.aField);
            if (aFieldExists) {
                const valueTemplate = generateFieldValueTemplate(field, mapping.aField);
                clause = `${field.name}=【【${valueTemplate}】】`;
            } else {
                clause = `${field.name}=【【{${field.name}}】】`;
            }
        } else {
            // 未匹配的字段使用目标字段名=【【目标字段名】】格式
            clause = `${field.name}=【【${field.name}】】`;
        }

        // 每5个字段换行
        if (index > 0 && index % 5 === 0) {
            return '\n' + clause;
        }
        return clause;
    });

    return mergeClauses.join(',\n');
}

// 生成完整SQL
function generateFullSQL(insertValuesSQL, mergeSetSQL) {
    const tableName = currentMapping.bTable.name || 'target_table';
    const template = sqlTemplates.merge_template;

    // 替换模板中的占位符
    let fullSQL = template
        .replace('【TABLE_NAME】', tableName)
        .replace('[INSERT_VALUES_FORMAT]', insertValuesSQL)
        .replace('[MERGE_SET_FORMAT]', mergeSetSQL);

    return fullSQL;
}

// 生成字段值模板
function generateFieldValueTemplate(field, sourceFieldName) {
    const fieldType = (field.type || '').toUpperCase();
    const isNullable = !field.required;

    // 检测字段类型并生成相应的模板
    if (isDateType(fieldType)) {
        return generateDateValueTemplate(sourceFieldName, field);
    } else if (isNumericType(fieldType)) {
        return generateNumericValueTemplate(sourceFieldName, field);
    } else if (isBooleanType(fieldType)) {
        return generateBooleanValueTemplate(sourceFieldName, field);
    } else {
        // 字符串类型
        return generateStringValueTemplate(sourceFieldName, field);
    }
}

// 生成默认值
function generateDefaultValue(field) {
    const fieldType = (field.type || '').toUpperCase();
    const isNullable = !field.required;

    if (field.defaultValue) {
        // 如果有默认值，使用默认值
        if (isDateType(fieldType)) {
            if (field.defaultValue.toUpperCase() === 'CURRENT_TIMESTAMP' ||
                field.defaultValue.toUpperCase() === 'NOW()') {
                return 'CURRENT_TIMESTAMP';
            } else {
                return `'${field.defaultValue}'`;
            }
        } else if (isNumericType(fieldType)) {
            return field.defaultValue;
        } else if (isBooleanType(fieldType)) {
            return field.defaultValue;
        } else {
            return `'${field.defaultValue}'`;
        }
    } else if (isNullable) {
        // 可为空且无默认值，使用NULL
        return 'NULL';
    } else {
        // 必填字段无默认值，根据类型提供合理的默认值
        if (isDateType(fieldType)) {
            return 'CURRENT_TIMESTAMP';
        } else if (isNumericType(fieldType)) {
            return '0';
        } else if (isBooleanType(fieldType)) {
            return 'FALSE';
        } else {
            return "''";
        }
    }
}

// 字符串类型模板
function generateStringValueTemplate(sourceFieldName, field) {
    const isNullable = !field.required;
    const template = isNullable ? sqlTemplates.string_nullable : sqlTemplates.string_notnull;
    return template.replace(/field_name/g, sourceFieldName);
}

// 日期类型模板
function generateDateValueTemplate(sourceFieldName, field) {
    const isNullable = !field.required;
    const template = isNullable ? sqlTemplates.date_nullable : sqlTemplates.date_notnull;
    return template.replace(/field_name/g, sourceFieldName);
}

// 数值类型模板
function generateNumericValueTemplate(sourceFieldName, field) {
    const isNullable = !field.required;
    const template = isNullable ? sqlTemplates.numeric_nullable : sqlTemplates.numeric_notnull;
    return template.replace(/field_name/g, sourceFieldName);
}

// 布尔类型模板
function generateBooleanValueTemplate(sourceFieldName, field) {
    // 布尔类型使用数值类型的模板
    const isNullable = !field.required;
    const template = isNullable ? sqlTemplates.numeric_nullable : sqlTemplates.numeric_notnull;
    return template.replace(/field_name/g, sourceFieldName);
}

// 必填字段检测函数
function isRequiredField(value) {
    if (!value) return false;

    const str = value.toString().toLowerCase().trim();

    // 直接的布尔值
    if (str === 'true' || str === 't') return true;
    if (str === 'false' || str === 'f') return false;

    // 中文判断
    if (str === '是' || str === '必填' || str === '非空') return true;
    if (str === '否' || str === '可选' || str === '可空') return false;

    // 数值判断（1表示必填，0表示可选）
    if (str === '1' || str === 'yes') return true;
    if (str === '0' || str === 'no') return false;

    // 特殊符号判断（勾号等）
    if (str === '✓' || str === '✔' || str === '☑') return true;
    if (str === '✗' || str === '✘' || str === '☐') return false;

    // 增强的判断：支持更多格式
    // 支持大写的TRUE/T
    if (str === 'TRUE' || str === 'T') return true;
    if (str === 'FALSE' || str === 'F') return false;

    // 支持勾选框符号（√、×等）
    if (str === '√' || str === '☑' || str === '✓' || str === '✔') return true;
    if (str === '×' || str === '✗' || str === '✘' || str === '☐') return false;

    // 其他包含"必填"、"非空"等关键词的情况
    if (str.includes('必填') || str.includes('非空') || str.includes('not null')) return true;
    if (str.includes('可空') || str.includes('null') || str.includes('optional')) return false;

    // 默认情况下，认为是可选的
    return false;
}

// 类型检测函数
function isDateType(fieldType) {
    const dateTypes = ['DATE', 'DATETIME', 'TIMESTAMP', 'TIME'];
    return dateTypes.some(type => fieldType.includes(type));
}

function isNumericType(fieldType) {
    const numericTypes = ['INT', 'INTEGER', 'BIGINT', 'SMALLINT', 'TINYINT',
                         'DECIMAL', 'NUMERIC', 'FLOAT', 'DOUBLE', 'REAL'];
    return numericTypes.some(type => fieldType.includes(type));
}

function isBooleanType(fieldType) {
    const booleanTypes = ['BOOLEAN', 'BOOL', 'BIT'];
    return booleanTypes.some(type => fieldType.includes(type));
}

// 保存映射
function saveMapping() {
    if (currentMapping.mappings.length === 0) {
        showMessage('没有映射关系可保存', 'warning');
        return;
    }

    try {
        // 创建自动备份
        createAutoBackup();

        const stmt = db.prepare(`
            INSERT INTO table_mappings
            (a_table_name, b_table_name, a_table_structure, b_table_structure, mappings)
            VALUES (?, ?, ?, ?, ?)
        `);

        stmt.run([
            currentMapping.aTable.name,
            currentMapping.bTable.name,
            JSON.stringify(currentMapping.aTable),
            JSON.stringify(currentMapping.bTable),
            JSON.stringify(currentMapping.mappings)
        ]);

        stmt.free();
        saveDatabase();

        // 标记数据已保存
        markDataSaved();

        showMessage('映射关系已保存', 'success');
        loadHistory();
    } catch (error) {
        showMessage('保存失败: ' + error.message, 'danger');
    }
}

// 加载历史记录
function loadHistory() {
    try {
        const stmt = db.prepare(`
            SELECT id, a_table_name, b_table_name, mappings, created_at
            FROM table_mappings
            ORDER BY created_at DESC
        `);

        const results = [];
        while (stmt.step()) {
            const row = stmt.getAsObject();
            row.mappingCount = JSON.parse(row.mappings).length;
            results.push(row);
        }

        stmt.free();

        displayHistory(results);
    } catch (error) {
        console.error('加载历史记录失败:', error);
    }
}

// 显示历史记录
function displayHistory(records) {
    const tbody = document.getElementById('historyTableBody');
    tbody.innerHTML = '';

    // 添加调试信息
    console.log('显示历史记录，记录数量:', records.length);

    // 检查localStorage状态
    const savedDb = localStorage.getItem('mappingDB');
    console.log('localStorage中是否有数据库:', !!savedDb);
    if (savedDb) {
        try {
            const dbData = JSON.parse(savedDb);
            console.log('localStorage数据库大小:', (JSON.stringify(dbData).length / 1024).toFixed(2), 'KB');
        } catch (e) {
            console.error('localStorage数据库解析失败:', e);
        }
    }

    if (records.length === 0) {
        tbody.innerHTML = `
            <tr>
                <td colspan="5" class="text-center text-muted">
                    暂无历史记录
                    <br>
                    <small class="text-muted">
                        localStorage状态: ${savedDb ? '有数据' : '无数据'}
                        ${savedDb && JSON.parse(savedDb).length > 0 ? ' (可能数据损坏)' : ''}
                    </small>
                </td>
            </tr>
        `;
        return;
    }

    records.forEach(record => {
        const tr = document.createElement('tr');
        tr.innerHTML = `
            <td>${new Date(record.created_at).toLocaleString()}</td>
            <td>${record.a_table_name}</td>
            <td>${record.b_table_name}</td>
            <td>${record.mappingCount}</td>
            <td>
                <button class="btn btn-sm btn-outline-primary" onclick="loadMapping(${record.id})">
                    <i class="bi bi-eye"></i> 查看
                </button>
                <button class="btn btn-sm btn-outline-danger" onclick="deleteMapping(${record.id})">
                    <i class="bi bi-trash"></i> 删除
                </button>
            </td>
        `;
        tbody.appendChild(tr);
    });
}

// 加载映射
function loadMapping(id) {
    try {
        const stmt = db.prepare(`
            SELECT a_table_structure, b_table_structure, mappings
            FROM table_mappings
            WHERE id = ?
        `);

        stmt.bind([id]);
        if (stmt.step()) {
            const row = stmt.getAsObject();
            currentMapping.aTable = JSON.parse(row.a_table_structure);
            currentMapping.bTable = JSON.parse(row.b_table_structure);
            currentMapping.mappings = JSON.parse(row.mappings);

            // 重置字段映射状态
            currentMapping.aTable.fields.forEach(field => {
                field.mapped = false;
            });
            currentMapping.bTable.fields.forEach(field => {
                field.mapped = false;
            });

            // 根据映射关系更新字段状态
            currentMapping.mappings.forEach(mapping => {
                const aField = currentMapping.aTable.fields.find(f => f.name === mapping.aField);
                const bField = currentMapping.bTable.fields.find(f => f.name === mapping.bField);
                if (aField) aField.mapped = true;
                if (bField) bField.mapped = true;
            });

            // 更新表信息
            updateTableInfo('A', currentMapping.aTable.fields);
            updateTableInfo('B', currentMapping.bTable.fields);

            // 切换到映射界面
            switchToMapping();

            showMessage('映射关系已加载', 'success');
        }

        stmt.free();
    } catch (error) {
        showMessage('加载映射失败: ' + error.message, 'danger');
    }
}

// 删除映射
function deleteMapping(id) {
    if (confirm('确定要删除这条映射记录吗？')) {
        try {
            const stmt = db.prepare('DELETE FROM table_mappings WHERE id = ?');
            stmt.run([id]);
            stmt.free();

            saveDatabase();
            loadHistory();

            showMessage('映射记录已删除', 'success');
        } catch (error) {
            showMessage('删除失败: ' + error.message, 'danger');
        }
    }
}

// 复制所有SQL
function copyAllSQL() {
    const sqlValues = document.getElementById('sqlValues').textContent;
    const sqlUpdate = document.getElementById('sqlUpdate').textContent;
    const sqlMerge = document.getElementById('sqlMerge').textContent;

    const allSQL = `-- INSERT VALUES格式
${sqlValues}

-- UPDATE SET格式
${sqlUpdate}

-- MERGE SET格式
${sqlMerge}`;

    navigator.clipboard.writeText(allSQL).then(() => {
        showMessage('SQL已复制到剪贴板', 'success');
    }).catch(() => {
        showMessage('复制失败，请手动复制', 'danger');
    });
}

// 清空所有历史记录
function clearAllHistory() {
    if (confirm('确定要清空所有历史记录吗？此操作不可恢复！建议先导出备份。')) {
        try {
            // 备份当前数据
            createAutoBackup();

            // 删除所有映射记录
            db.run('DELETE FROM table_mappings');

            // 保存更改
            saveDatabase();

            // 重新加载历史记录
            loadHistory();

            // 更新统计信息
            updateDataStats();

            showMessage('所有历史记录已清空', 'success');
        } catch (error) {
            console.error('清空历史记录失败:', error);
            showMessage('清空失败: ' + error.message, 'danger');
        }
    }
}

// 调试localStorage数据
function debugLocalStorage() {
    console.log('=== localStorage调试信息 ===');

    // 检查localStorage中的所有数据
    console.log('localStorage中的所有键:');
    for (let key in localStorage) {
        if (localStorage.hasOwnProperty(key)) {
            const value = localStorage[key];
            console.log(`- ${key}: ${value.length} 字符`);

            if (key === 'mappingDB') {
                try {
                    const dbData = JSON.parse(value);
                    console.log(`  - 数据库数据大小: ${(value.length / 1024).toFixed(2)} KB`);
                    console.log(`  - 数组长度: ${dbData.length}`);

                    // 尝试加载数据库并检查表
                    const SQL = window.initSqlJs;
                    if (SQL) {
                        initSqlJs({ locateFile: file => `./${file}` })
                            .then(sql => {
                                try {
                                    const testDb = new sql.Database(new Uint8Array(dbData));

                                    // 检查表是否存在
                                    const checkTableStmt = testDb.prepare("SELECT name FROM sqlite_master WHERE type='table'");
                                    console.log('  - 数据库中的表:');
                                    while (checkTableStmt.step()) {
                                        const row = checkTableStmt.getAsObject();
                                        console.log(`    * ${row.name}`);
                                    }
                                    checkTableStmt.free();

                                    // 检查历史记录数量
                                    const countStmt = testDb.prepare("SELECT COUNT(*) as count FROM table_mappings");
                                    if (countStmt.step()) {
                                        const countRow = countStmt.getAsObject();
                                        console.log(`  - 历史记录数量: ${countRow.count}`);
                                    }
                                    countStmt.free();

                                    testDb.close();
                                } catch (dbError) {
                                    console.error('  - 数据库测试失败:', dbError);
                                }
                            });
                    }
                } catch (e) {
                    console.error('  - 解析数据库数据失败:', e);
                }
            } else if (key === 'currentMapping') {
                try {
                    const mappingData = JSON.parse(value);
                    console.log(`  - 映射数据: ${mappingData.aTable?.name || '无源表'} -> ${mappingData.bTable?.name || '无目标表'}`);
                    console.log(`  - 映射数量: ${mappingData.mappings?.length || 0}`);
                    console.log(`  - 最后保存: ${mappingData.lastSaved || '未知'}`);
                } catch (e) {
                    console.error('  - 解析映射数据失败:', e);
                }
            }
        }
    }

    // 尝试重新加载历史记录
    console.log('\n=== 尝试重新加载历史记录 ===');
    try {
        loadHistory();
        console.log('历史记录重新加载完成');
    } catch (error) {
        console.error('重新加载历史记录失败:', error);
    }

    showMessage('调试信息已输出到控制台，请按F12查看', 'info');
}

// 显示消息
function showMessage(message, type = 'info') {
    const alertDiv = document.createElement('div');
    alertDiv.className = `alert alert-${type} alert-dismissible fade show position-fixed`;
    alertDiv.style.cssText = 'top: 20px; right: 20px; z-index: 9999; max-width: 500px; min-width: 300px;';
    alertDiv.innerHTML = `
        ${message}
        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
    `;

    document.body.appendChild(alertDiv);

    // 根据消息类型调整显示时间
    const displayTime = message.includes('未找到的字段') ? 10000 : 5000;

    setTimeout(() => {
        if (alertDiv.parentNode) {
            alertDiv.parentNode.removeChild(alertDiv);
        }
    }, displayTime);
}

// 绘制连线（使用SVG）
function drawConnections() {
    const svg = document.getElementById('connectionSvg');
    if (!svg) return;

    // 清空现有连线，保留defs
    const defs = svg.querySelector('defs');
    svg.innerHTML = '';
    if (defs) {
        svg.appendChild(defs);
    }

    // 获取容器的位置信息
    const aContainer = document.getElementById('aTableFields');
    const bContainer = document.getElementById('bTableFields');
    const connectionArea = document.getElementById('connectionArea');

    if (!aContainer || !bContainer || !connectionArea) return;

    const aRect = aContainer.getBoundingClientRect();
    const bRect = bContainer.getBoundingClientRect();
    const connectionRect = connectionArea.getBoundingClientRect();

    currentMapping.mappings.forEach((mapping, index) => {
        const aFieldCard = document.querySelector(`[data-field-name="${mapping.aField}"][data-table-type="A"]`);
        const bFieldCard = document.querySelector(`[data-field-name="${mapping.bField}"][data-table-type="B"]`);

        if (aFieldCard && bFieldCard) {
            const aFieldRect = aFieldCard.getBoundingClientRect();
            const bFieldRect = bFieldCard.getBoundingClientRect();

            // 计算连线坐标（从B表到A表）
            const startX = (bFieldRect.right - connectionRect.left); // B表字段右边
            const startY = (bFieldRect.top - connectionRect.top + bFieldRect.height / 2);
            const endX = (aFieldRect.left - connectionRect.left); // A表字段左边
            const endY = (aFieldRect.top - connectionRect.top + aFieldRect.height / 2);

            // 创建连接线
            const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');

            // 计算贝塞尔曲线控制点
            const midX = (startX + endX) / 2;
            const midY = Math.min(startY, endY) - 30;

            const d = `M ${startX} ${startY} Q ${midX} ${midY} ${endX} ${endY}`;

            path.setAttribute('d', d);
            path.setAttribute('class', 'mapping-connection');
            path.setAttribute('data-mapping-index', index);
            path.setAttribute('data-a-field', mapping.aField);
            path.setAttribute('data-b-field', mapping.bField);
            path.setAttribute('title', `${mapping.bField} → ${mapping.aField}`);

            // 添加事件监听
            path.addEventListener('click', () => {
                selectConnection(mapping, path);
            });

            path.addEventListener('contextmenu', (e) => {
                e.preventDefault();
                showConnectionContextMenu(e, mapping);
            });

            svg.appendChild(path);
        }
    });
}

// 选中连线
function selectConnection(mapping, pathElement) {
    // 移除之前的选中状态
    document.querySelectorAll('.mapping-connection').forEach(p => {
        p.classList.remove('selected');
    });

    // 添加选中状态
    pathElement.classList.add('selected');
    selectedConnection = mapping;

    // 高亮对应的字段卡片
    highlightFieldCards(mapping);

    showMessage(`已选中映射: ${mapping.bField} → ${mapping.aField}`, 'info');
}

// 高亮字段卡片
function highlightFieldCards(mapping) {
    // 移除所有高亮
    document.querySelectorAll('.field-card').forEach(card => {
        card.classList.remove('search-highlight');
    });

    // 高亮对应的字段卡片
    const aFieldCard = document.querySelector(`[data-field-name="${mapping.aField}"][data-table-type="A"]`);
    const bFieldCard = document.querySelector(`[data-field-name="${mapping.bField}"][data-table-type="B"]`);

    if (aFieldCard) {
        aFieldCard.classList.add('search-highlight');
        aFieldCard.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }

    if (bFieldCard) {
        bFieldCard.classList.add('search-highlight');
        bFieldCard.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
}

// 创建曲线路径
function createCurvedPath(svg, startX, startY, endX, endY, index) {
    const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');

    // 计算控制点
    const midX = (startX + endX) / 2;
    const midY = startY - 30;

    // 创建路径数据
    const d = `M ${startX} ${startY} Q ${midX} ${midY} ${endX} ${endY}`;

    path.setAttribute('d', d);
    path.setAttribute('class', 'mapping-connection');
    path.setAttribute('data-mapping-index', index);
    path.setAttribute('data-a-field', currentMapping.mappings[index].aField);
    path.setAttribute('data-b-field', currentMapping.mappings[index].bField);

    svg.appendChild(path);
    return path;
}

// 显示连线右键菜单
function showConnectionContextMenu(event, mapping) {
    const menu = document.getElementById('connectionContextMenu');
    selectedConnection = mapping;

    // 设置菜单位置
    menu.style.left = event.pageX + 'px';
    menu.style.top = event.pageY + 'px';
    menu.style.display = 'block';

    // 点击其他地方隐藏菜单
    document.addEventListener('click', hideConnectionContextMenu);
}

// 隐藏连线右键菜单
function hideConnectionContextMenu() {
    const menu = document.getElementById('connectionContextMenu');
    menu.style.display = 'none';
    document.removeEventListener('click', hideConnectionContextMenu);
}

// 通过连线删除映射
function deleteMappingByConnection() {
    if (!selectedConnection) return;

    const mappingIndex = currentMapping.mappings.findIndex(m =>
        m.aField === selectedConnection.aField && m.bField === selectedConnection.bField
    );

    if (mappingIndex !== -1) {
        const mapping = currentMapping.mappings[mappingIndex];

        // 移除映射
        currentMapping.mappings.splice(mappingIndex, 1);

        // 更新字段状态
        const aField = currentMapping.aTable.fields.find(f => f.name === mapping.aField);
        const bField = currentMapping.bTable.fields.find(f => f.name === mapping.bField);

        if (aField) aField.mapped = false;
        if (bField) bField.mapped = false;

        // 刷新显示
        displayFields();
        setupFieldDragAndDrop();

        showMessage(`已删除映射: ${mapping.bField} → ${mapping.aField}`, 'success');
    }

    hideConnectionContextMenu();
}

// 显示批量注释模态框
function showBatchCommentModal(tableType) {
    currentBatchTableType = tableType;
    const modal = new bootstrap.Modal(document.getElementById('batchCommentModal'));
    const title = document.getElementById('batchCommentTitle');
    const input = document.getElementById('batchCommentInput');

    title.textContent = `${tableType}表批量添加字段注释`;
    input.value = '';
    input.placeholder = `示例：\nuser_id：用户唯一标识\nuser_name：用户姓名\ncreate_time：创建时间`;

    modal.show();
}

// 应用批量注释
function applyBatchComments() {
    const input = document.getElementById('batchCommentInput');
    const text = input.value.trim();

    if (!text) {
        showMessage('请输入字段注释内容', 'warning');
        return;
    }

    const lines = text.split('\n');
    let updatedCount = 0;

    lines.forEach(line => {
        const match = line.match(/^([^:：]+)[:：]\s*(.+)$/);
        if (match) {
            const fieldName = match[1].trim();
            const comment = match[2].trim();

            const table = currentBatchTableType === 'A' ? currentMapping.aTable : currentMapping.bTable;
            const field = table.fields.find(f => f.name === fieldName);

            if (field) {
                field.comment = comment;
                updatedCount++;
            }
        }
    });

    if (updatedCount > 0) {
        showMessage(`成功更新${updatedCount}个字段的说明`, 'success');
        bootstrap.Modal.getInstance(document.getElementById('batchCommentModal')).hide();

        // 刷新显示
        if (typeof d3 !== 'undefined') {
            displayFieldsD3();
        } else {
            displayFields();
            setupFieldDragAndDrop();
        }
    } else {
        showMessage('未找到匹配的字段，请检查字段名格式', 'warning');
    }
}

// 目标表字段筛选 - 使用G6实现
function filterBTableFields(filterType) {
    // 根据筛选条件更新filteredBFields
    switch (filterType) {
        case 'matched':
            filteredBFields = currentMapping.bTable.fields.filter(field => field.mapped);
            break;
        case 'unmatched':
            filteredBFields = currentMapping.bTable.fields.filter(field => !field.mapped);
            break;
        default:
            filteredBFields = [...currentMapping.bTable.fields];
    }

    // 添加tableType属性
    filteredBFields.forEach(field => {
        field.tableType = 'B';
    });

    // 重新渲染桑基图
    if (typeof G6 !== 'undefined') {
        displayFieldsG6();
    } else {
        displayFields();
    }
}

// 源表字段搜索 - 使用G6实现
function filterATableFields(searchText) {
    if (!searchText.trim()) {
        filteredAFields = [...currentMapping.aTable.fields];
    } else {
        const searchLower = searchText.toLowerCase();

        filteredAFields = currentMapping.aTable.fields.filter(field => {
            const nameMatch = field.name.toLowerCase().includes(searchLower);
            const commentMatch = field.comment && field.comment.toLowerCase().includes(searchLower);

            // 简单的拼音首字母匹配
            const pinyinMatch = getPinyinInitial(field.name).toLowerCase().includes(searchLower);

            return nameMatch || commentMatch || pinyinMatch;
        });
    }

    // 添加tableType属性
    filteredAFields.forEach(field => {
        field.tableType = 'A';
    });

    // 重新渲染桑基图
    if (typeof G6 !== 'undefined') {
        displayFieldsG6();
    } else {
        displayFields();
    }
}

// 简单的拼音首字母匹配
function getPinyinInitial(text) {
    // 简单映射常见汉字到拼音首字母
    const pinyinMap = {
        '用': 'y', '户': 'h', '名': 'm', '姓': 'x', '时': 's', '间': 'j',
        '创': 'c', '建': 'j', '更': 'g', '新': 'x', '删': 's', '除': 'c',
        '修': 'x', '改': 'g', '查': 'c', '看': 'k', '状': 'z', '态': 't',
        '编': 'b', '号': 'h', '类': 'l', '型': 'x', '地': 'd', '址': 'z',
        '手': 's', '机': 'j', '邮': 'y', '箱': 'x', '电': 'd', '话': 'h',
        '生': 's', '日': 'r', '期': 'q', '年': 'n', '月': 'y', '日': 'r'
    };

    let result = '';
    for (let char of text) {
        result += pinyinMap[char] || char;
    }
    return result;
}

// 数据变化检测相关功能
function initDataChangeDetection() {
    // 保存初始数据状态
    lastSavedData = JSON.stringify(currentMapping);
    hasUnsavedChanges = false;
}

function markDataChanged() {
    hasUnsavedChanges = true;
    updateSaveStatus();
}

function markDataSaved() {
    hasUnsavedChanges = false;
    lastSavedData = JSON.stringify(currentMapping);
    updateSaveStatus();
}

function hasDataChanged() {
    const currentData = JSON.stringify(currentMapping);
    return currentData !== lastSavedData;
}

function updateSaveStatus() {
    const statusElement = document.getElementById('saveStatus');
    if (!statusElement) {
        // 创建保存状态显示元素
        createSaveStatusElement();
    }

    const status = document.getElementById('saveStatus');
    if (hasUnsavedChanges) {
        status.innerHTML = '<i class="bi bi-exclamation-circle text-warning"></i> 有未保存的更改';
        status.className = 'text-warning';
    } else {
        status.innerHTML = '<i class="bi bi-check-circle text-success"></i> 已自动保存';
        status.className = 'text-success';
    }
}

function createSaveStatusElement() {
    const statusDiv = document.createElement('div');
    statusDiv.id = 'saveStatus';
    statusDiv.className = 'position-fixed';
    statusDiv.style.cssText = 'bottom: 20px; left: 20px; z-index: 1000; font-size: 14px; padding: 8px 12px; background: rgba(255,255,255,0.9); border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);';
    document.body.appendChild(statusDiv);
}

// 自动保存功能
function startAutoSave() {
    // 清除现有的定时器
    if (autoSaveInterval) {
        clearInterval(autoSaveInterval);
    }

    // 每10秒自动保存一次
    autoSaveInterval = setInterval(() => {
        if (hasUnsavedChanges && hasDataChanged()) {
            performAutoSave();
        }
    }, 10000);
}

function performAutoSave() {
    try {
        // 保存当前映射到localStorage
        localStorage.setItem('currentMapping', JSON.stringify(currentMapping));

        // 保存自动保存记录
        const autoSaveRecord = {
            timestamp: new Date().toISOString(),
            data: currentMapping
        };

        const autoSaveHistory = JSON.parse(localStorage.getItem('autoSaveHistory') || '[]');
        autoSaveHistory.push(autoSaveRecord);

        // 只保留最近10条自动保存记录
        if (autoSaveHistory.length > 10) {
            autoSaveHistory.shift();
        }

        localStorage.setItem('autoSaveHistory', JSON.stringify(autoSaveHistory));

        markDataSaved();
        console.log('自动保存完成:', new Date().toLocaleString());

        // 显示保存成功提示（短暂显示）
        showAutoSaveNotification();

    } catch (error) {
        console.error('自动保存失败:', error);
    }
}

function showAutoSaveNotification() {
    const status = document.getElementById('saveStatus');
    if (status) {
        const originalHtml = status.innerHTML;
        const originalClass = status.className;

        status.innerHTML = '<i class="bi bi-cloud-check text-success"></i> 自动保存成功';
        status.className = 'text-success';

        setTimeout(() => {
            if (hasUnsavedChanges) {
                status.innerHTML = '<i class="bi bi-exclamation-circle text-warning"></i> 有未保存的更改';
                status.className = 'text-warning';
            } else {
                status.innerHTML = '<i class="bi bi-check-circle text-success"></i> 已自动保存';
                status.className = 'text-success';
            }
        }, 2000);
    }
}

function stopAutoSave() {
    if (autoSaveInterval) {
        clearInterval(autoSaveInterval);
        autoSaveInterval = null;
    }
}

// 页面关闭前警告
function setupBeforeUnloadWarning() {
    // 页面关闭或刷新前警告
    window.addEventListener('beforeunload', (e) => {
        if (hasUnsavedChanges && !isUserClosing) {
            e.preventDefault();
            e.returnValue = '您有未保存的更改，确定要离开吗？';
            return e.returnValue;
        }
    });

    // 监听页面可见性变化（页面被隐藏时自动保存）
    document.addEventListener('visibilitychange', () => {
        if (document.hidden && hasUnsavedChanges) {
            performAutoSave();
        }
    });
}

// 手动保存时调用
function manualSave() {
    performAutoSave();
    isUserClosing = true;
    setTimeout(() => {
        isUserClosing = false;
    }, 1000);
}

// 从映射界面保存映射关系
function saveMappingFromInterface() {
    if (currentMapping.mappings.length === 0) {
        showMessage('没有映射关系可保存', 'warning');
        return;
    }

    if (!currentMapping.aTable.name || !currentMapping.bTable.name) {
        showMessage('请先导入表结构', 'warning');
        return;
    }

    // 调用原有的保存映射函数
    saveMapping();
}

// SQL模板配置相关函数
function toggleTemplateConfig() {
    const panel = document.getElementById('templateConfigPanel');
    const icon = document.getElementById('templateConfigIcon');

    if (panel.style.display === 'none') {
        panel.style.display = 'block';
        icon.className = 'bi bi-chevron-up';
        loadTemplates();
    } else {
        panel.style.display = 'none';
        icon.className = 'bi bi-chevron-down';
    }
}

function updateTemplate(type, template) {
    sqlTemplates[type] = template;
    // 自动保存模板配置
    saveTemplates();
}

function updateTemplateAndRegenerate(type, template) {
    sqlTemplates[type] = template;
    // 自动保存模板配置
    saveTemplates();
    // 实时重新生成SQL
    regenerateSQLIfPossible();
}

function regenerateSQLIfPossible() {
    // 检查是否有映射关系，如果有则重新生成SQL
    if (currentMapping.mappings.length > 0 && currentMapping.aTable.fields.length > 0 && currentMapping.bTable.fields.length > 0) {
        const sqlValues = generateValuesSQL();
        const sqlUpdate = generateUpdateSQL();
        const sqlMerge = generateMergeSQL();
        const sqlFull = generateFullSQL(sqlValues, sqlMerge);

        document.getElementById('sqlValues').textContent = sqlValues;
        document.getElementById('sqlUpdate').textContent = sqlUpdate;
        document.getElementById('sqlMerge').textContent = sqlMerge;

        // 更新完整SQL显示
        const sqlFullElement = document.getElementById('sqlFull');
        if (sqlFullElement) {
            sqlFullElement.textContent = sqlFull;
        }

        showMessage('模板已更新，SQL已重新生成', 'info');
    }
}

function loadTemplates() {
    // 从localStorage加载模板配置
    const savedTemplates = localStorage.getItem('sqlTemplates');
    if (savedTemplates) {
        try {
            const templates = JSON.parse(savedTemplates);
            Object.assign(sqlTemplates, templates);
        } catch (e) {
            console.warn('加载模板配置失败:', e);
        }
    }

    // 更新7个模板框的值
    const stringNotNullElement = document.getElementById('stringNotNullTemplate');
    if (stringNotNullElement) {
        stringNotNullElement.value = sqlTemplates.string_notnull;
    }

    const stringNullableElement = document.getElementById('stringNullableTemplate');
    if (stringNullableElement) {
        stringNullableElement.value = sqlTemplates.string_nullable;
    }

    const numericNotNullElement = document.getElementById('numericNotNullTemplate');
    if (numericNotNullElement) {
        numericNotNullElement.value = sqlTemplates.numeric_notnull;
    }

    const numericNullableElement = document.getElementById('numericNullableTemplate');
    if (numericNullableElement) {
        numericNullableElement.value = sqlTemplates.numeric_nullable;
    }

    const dateNotNullElement = document.getElementById('dateNotNullTemplate');
    if (dateNotNullElement) {
        dateNotNullElement.value = sqlTemplates.date_notnull;
    }

    const dateNullableElement = document.getElementById('dateNullableTemplate');
    if (dateNullableElement) {
        dateNullableElement.value = sqlTemplates.date_nullable;
    }

    // 更新整体拼接模板
    const mergeTemplateElement = document.getElementById('mergeTemplate');
    if (mergeTemplateElement) {
        mergeTemplateElement.value = sqlTemplates.merge_template;
    }
}

function saveTemplates() {
    // 保存模板配置到localStorage
    localStorage.setItem('sqlTemplates', JSON.stringify(sqlTemplates));
    showMessage('模板配置已保存', 'success');
}

function resetTemplates() {
    if (confirm('确定要重置所有模板为默认配置吗？')) {
        // 重置为默认模板
        sqlTemplates = {
            // 字符串类型
            string_notnull: "'${json.field_name}'",
            string_nullable: "'${json.field_name!}'",

            // 数值类型
            numeric_notnull: "${json.field_name}",
            numeric_nullable: "<#if json.field_name??>${json.field_name}<#else>NULL</#if>",

            // 时间类型
            date_notnull: "cast('${json.field_name}' as datetime)",
            date_nullable: "<#if json.field_name??>cast('${json.field_name}' as datetime)<#else>NULL</#if>",

            // 整体拼接模板
            merge_template: "insert into 【TABLE_NAME】 [INSERT_VALUES_FORMAT] ON CONFLICT (yljgdm, jclsh, xgbz) DO UPDATE SET [MERGE_SET_FORMAT]"
        };

        // 更新7个模板框的值
        const stringNotNullElement = document.getElementById('stringNotNullTemplate');
        if (stringNotNullElement) {
            stringNotNullElement.value = sqlTemplates.string_notnull;
        }

        const stringNullableElement = document.getElementById('stringNullableTemplate');
        if (stringNullableElement) {
            stringNullableElement.value = sqlTemplates.string_nullable;
        }

        const numericNotNullElement = document.getElementById('numericNotNullTemplate');
        if (numericNotNullElement) {
            numericNotNullElement.value = sqlTemplates.numeric_notnull;
        }

        const numericNullableElement = document.getElementById('numericNullableTemplate');
        if (numericNullableElement) {
            numericNullableElement.value = sqlTemplates.numeric_nullable;
        }

        const dateNotNullElement = document.getElementById('dateNotNullTemplate');
        if (dateNotNullElement) {
            dateNotNullElement.value = sqlTemplates.date_notnull;
        }

        const dateNullableElement = document.getElementById('dateNullableTemplate');
        if (dateNullableElement) {
            dateNullableElement.value = sqlTemplates.date_nullable;
        }

        // 更新整体拼接模板
        const mergeTemplateElement = document.getElementById('mergeTemplate');
        if (mergeTemplateElement) {
            mergeTemplateElement.value = sqlTemplates.merge_template;
        }

        // 保存到localStorage
        saveTemplates();
        showMessage('模板已重置为默认配置', 'info');

        // 如果有映射关系，重新生成SQL
        setTimeout(() => {
            regenerateSQLIfPossible();
        }, 100);
    }
}

// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', () => {
    initDatabase();
    setupFileUpload();

    // 加载保存的当前映射
    loadCurrentMapping();

    // 清理旧的自动保存记录
    cleanupAutoSaveRecords();

    // 加载SQL模板配置
    loadTemplates();

    // 初始化数据变化检测和自动保存
    initDataChangeDetection();
    startAutoSave();

    // 设置页面关闭前警告
    setupBeforeUnloadWarning();

    // 监听测试数据加载
    window.addEventListener('message', (event) => {
        if (event.data.type === 'LOAD_TEST_DATA') {
            try {
                currentMapping = event.data.data;
                updateTableInfo('A', currentMapping.aTable.fields);
                updateTableInfo('B', currentMapping.bTable.fields);
                checkMappingReady();

                // 保存到localStorage
                saveCurrentMapping();

                showMessage('测试数据加载成功！', 'success');
            } catch (error) {
                showMessage('测试数据加载失败: ' + error.message, 'danger');
            }
        }
    });

    // 监听窗口大小变化，重绘连线
    window.addEventListener('resize', () => {
        if (document.getElementById('mapping-tab').classList.contains('active')) {
            setTimeout(() => {
                if (typeof d3 !== 'undefined') {
                    drawConnectionsD3();
                } else {
                    drawConnections();
                }
            }, 100);
        }
    });

    // 启动定期备份（每5分钟）
    setInterval(() => {
        if (currentMapping.mappings.length > 0) {
            createAutoBackup();
        }
    }, 5 * 60 * 1000);

    // 启动定期清理（每天）
    setInterval(() => {
        cleanupOldBackups();
    }, 24 * 60 * 60 * 1000);

    // 页面卸载时创建备份
    window.addEventListener('beforeunload', () => {
        if (currentMapping.mappings.length > 0) {
            createAutoBackup();
        }
    });
});

// ===== 表格布局相关函数 =====

// 表格布局显示字段映射
function displayFieldsTable() {
    if (!currentMapping.aTable || !currentMapping.bTable) return;

    // 初始化字段数据
    filteredBFields = currentMapping.bTable.fields.map(field => ({
        ...field,
        tableType: 'B',
        mapped: false
    }));

    filteredAFields = currentMapping.aTable.fields.map(field => ({
        ...field,
        tableType: 'A',
        mapped: false,
        referenceCount: 0 // 添加引用计数
    }));

    // 更新映射状态和引用计数
    currentMapping.mappings.forEach(mapping => {
        const bField = filteredBFields.find(f => f.name === mapping.bField);
        const aField = filteredAFields.find(f => f.name === mapping.aField);
        if (bField) bField.mapped = true;
        if (aField) {
            aField.mapped = true;
            aField.referenceCount++;
        }
    });

    // 渲染表格
    renderTargetFieldsTable();
    renderSourceFieldsList();
}

// 渲染目标字段表格
function renderTargetFieldsTable() {
    const tbody = document.getElementById('targetFieldsTableBody');
    if (!tbody) return;

    tbody.innerHTML = '';

    filteredBFields.forEach(field => {
        const row = document.createElement('tr');
        row.className = field.mapped ? 'matched' : '';
        row.setAttribute('data-field-name', field.name);
        row.setAttribute('data-table-type', 'B');

        // 操作列
        const actionCell = document.createElement('td');
        if (field.mapped) {
            const unbindBtn = document.createElement('button');
            unbindBtn.className = 'btn btn-sm btn-outline-danger';
            unbindBtn.innerHTML = '<i class="bi bi-unlink"></i>';
            unbindBtn.title = '取消绑定';
            unbindBtn.onclick = (e) => {
                e.stopPropagation();
                unbindField(field.name);
            };
            actionCell.appendChild(unbindBtn);
        } else {
            const placeholder = document.createElement('span');
            placeholder.className = 'text-muted';
            placeholder.innerHTML = '<i class="bi bi-dash"></i>';
            actionCell.appendChild(placeholder);
        }

        // 字段名列
        const nameCell = document.createElement('td');
        const nameSpan = document.createElement('span');
        nameSpan.className = 'field-name';
        nameSpan.textContent = field.name;

        // 添加必填/非空标记
        if (field.required) {
            const requiredBadge = document.createElement('span');
            requiredBadge.className = 'badge bg-danger ms-1';
            requiredBadge.innerHTML = '<i class="bi bi-exclamation-circle-fill"></i> 必填';
            requiredBadge.title = '必填字段';
            nameSpan.appendChild(requiredBadge);
        }

        nameCell.appendChild(nameSpan);

        // 类型列
        const typeCell = document.createElement('td');
        const typeSpan = document.createElement('span');
        typeSpan.className = 'field-type';
        typeSpan.textContent = field.type || '';
        typeCell.appendChild(typeSpan);

        // 注释列
        const commentCell = document.createElement('td');
        const commentSpan = document.createElement('span');
        commentSpan.className = 'field-comment';
        commentSpan.textContent = field.comment || '';
        commentCell.appendChild(commentSpan);

        // 匹配的源字段列
        const mappedCell = document.createElement('td');
        if (field.mapped) {
            const mapping = currentMapping.mappings.find(m => m.bField === field.name);
            if (mapping) {
                const sourceField = currentMapping.aTable.fields.find(f => f.name === mapping.aField);
                if (sourceField) {
                    const mappedDiv = document.createElement('div');
                    mappedDiv.className = 'mapped-field';
                    mappedDiv.innerHTML = `
                        <span class="mapped-field-name">${sourceField.name}</span>
                        <span class="mapped-field-type">${sourceField.type || ''}</span>
                    `;
                    mappedCell.appendChild(mappedDiv);
                }
            }
        }

        // 添加单元格到行
        row.appendChild(actionCell);
        row.appendChild(nameCell);
        row.appendChild(typeCell);
        row.appendChild(commentCell);
        row.appendChild(mappedCell);

        // 添加双击事件编辑注释
        row.addEventListener('dblclick', () => {
            openEditCommentModal(field.name, 'B', field.comment);
        });

        // 添加选中效果
        row.addEventListener('click', (e) => {
            // 如果点击的是按钮，不触发选中
            if (e.target.tagName === 'BUTTON' || e.target.closest('button')) {
                return;
            }
            selectTargetField(field, row);
        });

        // 设置拖拽目标
        row.addEventListener('dragover', handleDragOver);
        row.addEventListener('drop', (e) => handleDrop(e, field));
        row.addEventListener('dragleave', handleDragLeave);

        tbody.appendChild(row);
    });
}

// 渲染源字段列表
function renderSourceFieldsList() {
    const container = document.getElementById('sourceFieldsList');
    if (!container) return;

    container.innerHTML = '';

    filteredAFields.forEach(field => {
        const fieldDiv = document.createElement('div');
        fieldDiv.className = `source-field-item ${field.mapped ? 'mapped' : ''}`;
        fieldDiv.setAttribute('data-field-name', field.name);
        fieldDiv.setAttribute('data-table-type', 'A');
        fieldDiv.style.position = 'relative'; // 为引用计数器提供定位
        fieldDiv.draggable = true; // 允许重复拖拽

        // 第一行：字段名、类型、非空标记
        const firstRow = document.createElement('div');
        firstRow.className = 'source-field-first-row';

        const nameSpan = document.createElement('div');
        nameSpan.className = 'source-field-name';
        nameSpan.textContent = field.name;

        const typeSpan = document.createElement('div');
        typeSpan.className = 'source-field-type';
        typeSpan.textContent = field.type || '';

          firstRow.appendChild(nameSpan);
        firstRow.appendChild(typeSpan);

        // 添加必填标记
        if (field.required) {
            const requiredSpan = document.createElement('div');
            requiredSpan.className = 'source-field-required';
            requiredSpan.innerHTML = '<i class="bi bi-exclamation-circle-fill"></i> 必填';
            requiredSpan.style.color = '#dc3545';
            requiredSpan.style.fontSize = '10px';
            requiredSpan.style.fontWeight = 'bold';
            firstRow.appendChild(requiredSpan);
        }

        // 第二行：注释
        const commentDiv = document.createElement('div');
        commentDiv.className = 'source-field-comment';
        commentDiv.textContent = field.comment || '';

        // 添加到字段元素
        fieldDiv.appendChild(firstRow);
        fieldDiv.appendChild(commentDiv);

        // 添加引用计数标记
        if (field.referenceCount > 0) {
            const referenceBadge = document.createElement('div');
            referenceBadge.className = 'source-field-reference-count';
            referenceBadge.textContent = field.referenceCount;
            fieldDiv.appendChild(referenceBadge);
        }

        // 添加双击事件编辑注释
        fieldDiv.addEventListener('dblclick', () => {
            openEditCommentModal(field.name, 'A', field.comment);
        });

        // 添加拖拽事件
        fieldDiv.addEventListener('dragstart', handleDragStart);
        fieldDiv.addEventListener('dragend', handleDragEnd);

        container.appendChild(fieldDiv);
    });
}

// 拖拽开始
function handleDragStart(e) {
    const fieldName = e.target.getAttribute('data-field-name');
    const tableType = e.target.getAttribute('data-table-type');

    e.dataTransfer.effectAllowed = 'link';
    e.dataTransfer.setData('fieldName', fieldName);
    e.dataTransfer.setData('tableType', tableType);

    e.target.classList.add('dragging');
}

// 拖拽结束
function handleDragEnd(e) {
    e.target.classList.remove('dragging');
}

// 拖拽经过
function handleDragOver(e) {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'link';

    const row = e.currentTarget;
    row.classList.add('drag-over');

    // 获取拖拽的源字段信息
    const draggedData = e.dataTransfer.getData('text/plain');
    if (draggedData) {
        try {
            const sourceData = JSON.parse(draggedData);
            highlightTargetFieldForDrag(sourceData.fieldName, row);
        } catch (error) {
            console.error('解析拖拽数据失败:', error);
        }
    }
}

// 拖拽离开
function handleDragLeave(e) {
    const row = e.currentTarget;
    row.classList.remove('drag-over');
    removeDragHighlight();
}

// 高亮显示目标字段
function highlightTargetFieldForDrag(sourceFieldName, targetRow) {
    // 移除之前的高亮
    removeDragHighlight();

    // 为当前目标行添加特殊高亮
    targetRow.classList.add('drag-target-highlight');

    // 获取源字段信息
    const sourceField = currentMapping.aTable.fields.find(f => f.name === sourceFieldName);
    if (!sourceField) return;

    // 在目标行中显示源字段信息提示
    const targetField = currentMapping.bTable.fields.find(f => f.name === targetRow.getAttribute('data-field-name'));
    if (!targetField) return;

    // 计算相似度并显示
    const similarity = calculateFieldSimilarity(sourceField, targetField);

    // 创建或更新提示信息
    let tooltip = targetRow.querySelector('.drag-tooltip');
    if (!tooltip) {
        tooltip = document.createElement('div');
        tooltip.className = 'drag-tooltip';
        targetRow.appendChild(tooltip);
    }

    tooltip.innerHTML = `
        <div class="drag-tooltip-content">
            <strong>源字段: ${sourceField.name}</strong><br>
            类型: ${sourceField.type || '未知'}<br>
            注释: ${sourceField.comment || '无'}<br>
            相似度: ${(similarity * 100).toFixed(1)}%
        </div>
    `;

    // 高亮对应的目标字段列（在整个界面上突出显示）
    highlightTargetFieldInMapping(targetField.name);
}

// 移除拖拽高亮
function removeDragHighlight() {
    // 移除所有高亮样式
    document.querySelectorAll('.drag-target-highlight').forEach(row => {
        row.classList.remove('drag-target-highlight');
    });

    // 移除目标字段映射高亮
    document.querySelectorAll('.target-field-highlight').forEach(elem => {
        elem.classList.remove('target-field-highlight');
    });

    // 移除所有提示信息
    document.querySelectorAll('.drag-tooltip').forEach(tooltip => {
        tooltip.remove();
    });
}

// 高亮目标字段在映射关系中
function highlightTargetFieldInMapping(targetFieldName) {
    // 在左侧目标表中找到对应的字段行并高亮
    const targetRow = document.querySelector(`#targetFieldsTableBody tr[data-field-name="${targetFieldName}"]`);
    if (targetRow) {
        targetRow.classList.add('target-field-highlight');
        targetRow.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }

    // 在右侧源表中找到映射到此目标字段的源字段并高亮
    const mapping = currentMapping.mappings.find(m => m.bField === targetFieldName);
    if (mapping) {
        const sourceFieldDiv = document.querySelector(`#sourceFieldsList [data-field-name="${mapping.aField}"]`);
        if (sourceFieldDiv) {
            sourceFieldDiv.classList.add('target-field-highlight');
        }
    }
}

// 放置处理
function handleDrop(e, targetField) {
    e.preventDefault();
    const row = e.currentTarget;
    row.classList.remove('drag-over');

    // 移除拖拽高亮
    removeDragHighlight();

    const sourceFieldName = e.dataTransfer.getData('fieldName');
    const sourceTableType = e.dataTransfer.getData('tableType');

    // 确保是从源表拖拽到目标表
    if (sourceTableType === 'A' && targetField.tableType === 'B') {
        // 检查目标字段是否已经映射（目标表字段不能重复匹配）
        const existingMapping = currentMapping.mappings.find(m => m.bField === targetField.name);
        if (!existingMapping) {
            // 创建新映射
            currentMapping.mappings.push({
                bField: targetField.name,
                aField: sourceFieldName
            });

            // 更新目标字段状态
            targetField.mapped = true;

            // 更新源字段状态（增加引用计数）
            const sourceField = filteredAFields.find(f => f.name === sourceFieldName);
            if (sourceField) {
                sourceField.mapped = true;
                sourceField.referenceCount++;
            }

            // 重新渲染
            renderTargetFieldsTable();
            renderSourceFieldsList();

            // 保存到localStorage
            saveCurrentMapping();

            showMessage(`已映射: ${targetField.name} ← ${sourceFieldName}`, 'success');
        } else {
            showMessage('该目标字段已经映射过了', 'warning');
        }
    }
}

// 取消绑定
function unbindField(fieldName) {
    const mappingIndex = currentMapping.mappings.findIndex(m => m.bField === fieldName);
    if (mappingIndex !== -1) {
        const mapping = currentMapping.mappings[mappingIndex];
        currentMapping.mappings.splice(mappingIndex, 1);

        // 更新目标字段状态
        const bField = filteredBFields.find(f => f.name === fieldName);
        if (bField) bField.mapped = false;

        // 更新源字段状态（减少引用计数）
        const aField = filteredAFields.find(f => f.name === mapping.aField);
        if (aField) {
            aField.referenceCount--;
            // 如果引用计数为0，则标记为未映射
            if (aField.referenceCount <= 0) {
                aField.mapped = false;
                aField.referenceCount = 0;
            }
        }

        // 重新渲染
        renderTargetFieldsTable();
        renderSourceFieldsList();

        // 自动保存
        autoSave();

        showMessage(`已取消绑定: ${fieldName}`, 'info');
    }
}

// 目标表字段搜索
function filterTargetFields(searchText) {
    if (!searchText.trim()) {
        filteredBFields = currentMapping.bTable.fields.map(field => ({
            ...field,
            tableType: 'B',
            mapped: currentMapping.mappings.some(m => m.bField === field.name)
        }));
    } else {
        const searchLower = searchText.toLowerCase();
        filteredBFields = currentMapping.bTable.fields.filter(field => {
            const nameMatch = field.name.toLowerCase().includes(searchLower);
            const commentMatch = field.comment && field.comment.toLowerCase().includes(searchLower);
            return nameMatch || commentMatch;
        }).map(field => ({
            ...field,
            tableType: 'B',
            mapped: currentMapping.mappings.some(m => m.bField === field.name)
        }));
    }

    renderTargetFieldsTable();
}

// 目标表字段筛选（已匹配、未匹配、全部）
function filterTargetFieldsByType(filterType) {
    switch (filterType) {
        case 'matched':
            filteredBFields = currentMapping.bTable.fields.filter(field =>
                currentMapping.mappings.some(m => m.bField === field.name)
            ).map(field => ({
                ...field,
                tableType: 'B',
                mapped: true
            }));
            break;
        case 'unmatched':
            filteredBFields = currentMapping.bTable.fields.filter(field =>
                !currentMapping.mappings.some(m => m.bField === field.name)
            ).map(field => ({
                ...field,
                tableType: 'B',
                mapped: false
            }));
            break;
        default:
            filteredBFields = currentMapping.bTable.fields.map(field => ({
                ...field,
                tableType: 'B',
                mapped: currentMapping.mappings.some(m => m.bField === field.name)
            }));
    }

    renderTargetFieldsTable();
}

// 源表字段搜索
function filterSourceFields(searchText) {
    if (!searchText.trim()) {
        filteredAFields = currentMapping.aTable.fields.map(field => ({
            ...field,
            tableType: 'A',
            mapped: currentMapping.mappings.some(m => m.aField === field.name)
        }));
    } else {
        const searchLower = searchText.toLowerCase();
        filteredAFields = currentMapping.aTable.fields.filter(field => {
            const nameMatch = field.name.toLowerCase().includes(searchLower);
            const commentMatch = field.comment && field.comment.toLowerCase().includes(searchLower);
            return nameMatch || commentMatch;
        }).map(field => ({
            ...field,
            tableType: 'A',
            mapped: currentMapping.mappings.some(m => m.aField === field.name)
        }));
    }

    renderSourceFieldsList();
}

// 编辑注释相关函数
function openEditCommentModal(fieldName, tableType, currentComment) {
    document.getElementById('editFieldName').value = fieldName;
    document.getElementById('editComment').value = currentComment || '';
    document.getElementById('editTableType').value = tableType;
    document.getElementById('editOriginalFieldName').value = fieldName;

    const modal = new bootstrap.Modal(document.getElementById('editCommentModal'));
    modal.show();
}


function saveComment() {
    const fieldName = document.getElementById('editOriginalFieldName').value;
    const tableType = document.getElementById('editTableType').value;
    const newComment = document.getElementById('editComment').value;

    // 更新数据
    const table = tableType === 'A' ? currentMapping.aTable : currentMapping.bTable;
    const field = table.fields.find(f => f.name === fieldName);
    if (field) {
        field.comment = newComment;
    }

    // 更新过滤后的数据
    const filteredFields = tableType === 'A' ? filteredAFields : filteredBFields;
    const filteredField = filteredFields.find(f => f.name === fieldName);
    if (filteredField) {
        filteredField.comment = newComment;
    }

    // 标记数据已更改
    markDataChanged();

    // 重新渲染界面
    if (tableType === 'A') {
        renderSourceFieldsList();
    } else {
        displayFieldsTable();
    }

    // 关闭模态框
    const modal = bootstrap.Modal.getInstance(document.getElementById('editCommentModal'));
    modal.hide();

    // 自动保存
    autoSave();

    showMessage('注释已保存', 'success');
}

function openBatchCommentModal(tableType) {
    document.getElementById('batchTableType').value = tableType;

    // 获取字段列表
    const table = tableType === 'A' ? currentMapping.aTable : currentMapping.bTable;
    if (!table || !table.fields) {
        document.getElementById('batchCommentText').value = '';
    } else {
        // 分离空注释和非空注释的字段
        const emptyCommentFields = [];
        const hasCommentFields = [];

        table.fields.forEach(field => {
            const comment = field.comment || '';
            // 检查是否为空注释（包括[NULL]、null、空字符串等）
            if (comment === '' || comment === '[NULL]' || comment === 'null' || comment === 'NULL') {
                emptyCommentFields.push(field.name + ':');
            } else {
                hasCommentFields.push(field.name + ':' + comment);
            }
        });

        // 空注释字段在前，有注释字段在后，按照用户要求
        const allFields = [...emptyCommentFields, ...hasCommentFields];
        document.getElementById('batchCommentText').value = allFields.join('\n');
    }

    const modal = new bootstrap.Modal(document.getElementById('batchCommentModal'));
    modal.show();
}

function saveBatchComment() {
    const tableType = document.getElementById('batchTableType').value;
    const comment = document.getElementById('batchCommentText').value;

    if (!comment.trim()) {
        showMessage('请输入注释内容', 'warning');
        return;
    }

    // 解析注释文本
    const commentLines = comment.trim().split('\n');
    const commentMap = new Map();
    // 支持更灵活的字段名格式：字母、数字、中文、下划线、中划线等
    const validFieldNamePattern = /^[\u4e00-\u9fa5a-zA-Z_][\u4e00-\u9fa5a-zA-Z0-9_\-]*$/;

    commentLines.forEach(line => {
        // 支持中英文冒号
        let colonIndex = line.indexOf(':');
        if (colonIndex === -1) {
            colonIndex = line.indexOf('：');
        }

        if (colonIndex > 0) {
            const fieldName = line.substring(0, colonIndex).trim();
            const fieldComment = line.substring(colonIndex + 1).trim();

            // 只添加符合字段名格式的行
            if (validFieldNamePattern.test(fieldName) && fieldName.length > 0) {
                commentMap.set(fieldName, fieldComment);
            }
        }
    });

    if (commentMap.size === 0) {
        showMessage('没有找到有效的字段注释格式（字段名:注释）', 'warning');
        return;
    }

    // 获取目标表的所有字段名
    const table = tableType === 'A' ? currentMapping.aTable : currentMapping.bTable;
    const tableFieldNames = new Set(table.fields.map(field => field.name));

    // 统计处理结果
    let updatedCount = 0;
    let notFoundFields = [];

    // 更新数据
    table.fields.forEach(field => {
        if (commentMap.has(field.name)) {
            field.comment = commentMap.get(field.name);
            updatedCount++;
        }
    });

    // 更新过滤后的数据
    const filteredFields = tableType === 'A' ? filteredAFields : filteredBFields;
    filteredFields.forEach(field => {
        if (commentMap.has(field.name)) {
            field.comment = commentMap.get(field.name);
        }
    });

    // 检查哪些字段没有找到
    commentMap.forEach((comment, fieldName) => {
        if (!tableFieldNames.has(fieldName)) {
            notFoundFields.push(fieldName);
        }
    });

    // 标记数据已更改（只有实际更新了才标记）
    if (updatedCount > 0) {
        markDataChanged();
    }

    // 重新渲染界面
    if (tableType === 'A') {
        renderSourceFieldsList();
    } else {
        displayFieldsTable();
    }

    // 关闭模态框
    const modal = bootstrap.Modal.getInstance(document.getElementById('batchCommentModal'));
    modal.hide();

    // 构建提示消息
    let message = `批量设置注释完成`;
    let messageType = 'success';

    if (updatedCount > 0) {
        message += `，成功更新 ${updatedCount} 个字段`;
    }

    if (notFoundFields.length > 0) {
        messageType = 'warning';

        // 格式化未找到的字段列表
        let fieldList = '';
        if (notFoundFields.length <= 5) {
            // 字段较少时，用顿号分隔
            fieldList = notFoundFields.join('、');
        } else {
            // 字段较多时，分行显示，每行最多5个
            for (let i = 0; i < notFoundFields.length; i += 5) {
                const chunk = notFoundFields.slice(i, i + 5);
                fieldList += chunk.join('、');
                if (i + 5 < notFoundFields.length) {
                    fieldList += '<br>';
                }
            }
        }

        if (updatedCount > 0) {
            message += `，但有 ${notFoundFields.length} 个字段未找到<br><strong>未找到的字段：</strong><br>${fieldList}`;
        } else {
            message = `未找到匹配的字段<br><strong>未找到的字段：</strong><br>${fieldList}`;
        }
    }

    if (updatedCount === 0 && notFoundFields.length === 0) {
        message = '没有字段被更新，请检查字段名格式是否正确';
        messageType = 'info';
    }

    showMessage(message, messageType);

    // 在控制台输出详细信息，方便用户查看
    if (notFoundFields.length > 0) {
        console.group('批量注释 - 字段匹配详情');
        console.log('表类型:', tableType === 'A' ? '源表(A)' : '目标表(B)');
        console.log('表中的所有字段:', Array.from(tableFieldNames).sort());
        console.log('未匹配的字段:', notFoundFields.sort());
        console.log('成功匹配的字段:', Array.from(commentMap.keys()).filter(name => tableFieldNames.has(name)).sort());
        console.groupEnd();
    }

    // 自动保存
    autoSave();
}

// 计算编辑距离
function calculateEditDistance(str1, str2) {
    const m = str1.length;
    const n = str2.length;
    const dp = Array(m + 1).fill().map(() => Array(n + 1).fill(0));

    for (let i = 0; i <= m; i++) {
        dp[i][0] = i;
    }
    for (let j = 0; j <= n; j++) {
        dp[0][j] = j;
    }

    for (let i = 1; i <= m; i++) {
        for (let j = 1; j <= n; j++) {
            if (str1[i - 1] === str2[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1;
            }
        }
    }

    return dp[m][n];
}

// 计算字段相似度
function calculateFieldSimilarity(field1, field2) {
    let score = 0;

    // 字段名相似度（权重40%）
    const nameDistance = calculateEditDistance(field1.name.toLowerCase(), field2.name.toLowerCase());
    const maxNameLength = Math.max(field1.name.length, field2.name.length);
    const nameSimilarity = 1 - (nameDistance / maxNameLength);
    score += nameSimilarity * 0.4;

    // 注释相似度（权重40%）
    if (field1.comment && field2.comment) {
        const commentDistance = calculateEditDistance(field1.comment.toLowerCase(), field2.comment.toLowerCase());
        const maxCommentLength = Math.max(field1.comment.length, field2.comment.length);
        const commentSimilarity = 1 - (commentDistance / maxCommentLength);
        score += commentSimilarity * 0.4;
    }

    // 类型相似度（权重20%）
    if (field1.type && field2.type) {
        const typeSimilarity = field1.type === field2.type ? 1 : 0;
        score += typeSimilarity * 0.2;
    }

    return score;
}

// 选中目标字段
function selectTargetField(field, rowElement) {
    // 移除其他选中效果
    document.querySelectorAll('#targetFieldsTableBody tr').forEach(tr => {
        tr.classList.remove('table-active', 'selected-field');
    });

    // 添加选中效果
    rowElement.classList.add('table-active', 'selected-field');

    // 排序源字段
    sortSourceFields(field);
}

// 智能排序源字段
function sortSourceFields(selectedTargetField) {
    if (!selectedTargetField) {
        renderSourceFieldsList();
        return;
    }

    // 为每个源字段计算排序分数
    const sourceFieldsWithScore = filteredAFields.map(sourceField => {
        let score = 0;
        let priority = 0;

        // 1. 已匹配记录优先级最高
        const isMapped = currentMapping.mappings.some(m => m.bField === selectedTargetField.name && m.aField === sourceField.name);
        if (isMapped) {
            priority = 3;
            score = 1000;
        } else {
            // 2. 计算相似度分数
            score = calculateFieldSimilarity(sourceField, selectedTargetField) * 100;
            priority = 2;
        }

        // 3. 字段名升序排序（作为最后的排序条件）
        return {
            ...sourceField,
            sortScore: score,
            sortPriority: priority,
            nameLower: sourceField.name.toLowerCase()
        };
    });

    // 排序：先按优先级，再按分数，最后按字段名
    sourceFieldsWithScore.sort((a, b) => {
        if (a.sortPriority !== b.sortPriority) {
            return b.sortPriority - a.sortPriority;
        }
        if (a.sortScore !== b.sortScore) {
            return b.sortScore - a.sortScore;
        }
        return a.nameLower.localeCompare(b.nameLower);
    });

    // 更新过滤后的字段顺序
    filteredAFields = sourceFieldsWithScore;

    // 重新渲染源字段列表
    renderSourceFieldsList();
}

// 数据变动自动保存功能
let autoSaveTimer = null;
let lastSaveData = null;

function autoSave() {
    // 清除之前的定时器
    if (autoSaveTimer) {
        clearTimeout(autoSaveTimer);
    }

    // 设置新的定时器，延迟2秒保存
    autoSaveTimer = setTimeout(() => {
        performAutoSave();
    }, 2000);
}

function performAutoSave() {
    if (!currentMapping.aTable || !currentMapping.bTable) {
        return;
    }

    // 生成当前数据的快照
    const currentData = {
        aTable: JSON.stringify(currentMapping.aTable),
        bTable: JSON.stringify(currentMapping.bTable),
        mappings: JSON.stringify(currentMapping.mappings)
    };

    // 检查是否有变化
    if (lastSaveData && JSON.stringify(currentData) === JSON.stringify(lastSaveData)) {
        return; // 没有变化，不需要保存
    }

    try {
        // 保存到本地存储
        const autoSaveKey = `autosave_${new Date().getTime()}`;
        const saveData = {
            id: autoSaveKey,
            timestamp: new Date().toISOString(),
            aTable: currentMapping.aTable,
            bTable: currentMapping.bTable,
            mappings: currentMapping.mappings
        };

        // 保存到localStorage
        localStorage.setItem(autoSaveKey, JSON.stringify(saveData));

        // 保存到数据库（如果已初始化）
        if (db) {
            const stmt = db.prepare(`
                INSERT OR REPLACE INTO table_mappings
                (id, a_table_structure, b_table_structure, mappings, created_at)
                VALUES (?, ?, ?, ?, ?)
            `);

            stmt.bind([
                autoSaveKey,
                JSON.stringify(currentMapping.aTable),
                JSON.stringify(currentMapping.bTable),
                JSON.stringify(currentMapping.mappings),
                new Date().toISOString()
            ]);
            stmt.step();
            stmt.free();
        }

        lastSaveData = currentData;
        console.log('自动保存成功:', autoSaveKey);

    } catch (error) {
        console.error('自动保存失败:', error);
    }
}

// 获取自动保存的记录
function getAutoSaveRecords() {
    const records = [];

    // 从localStorage获取
    for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i);
        if (key && key.startsWith('autosave_')) {
            try {
                const data = JSON.parse(localStorage.getItem(key));
                records.push({
                    id: data.id,
                    timestamp: data.timestamp,
                    aTable: data.aTable,
                    bTable: data.bTable,
                    mappings: data.mappings,
                    isAutoSave: true
                });
            } catch (error) {
                console.error('解析自动保存记录失败:', error);
            }
        }
    }

    return records.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp));
}

// 清理旧的自动保存记录（保留最近10个）
function cleanupAutoSaveRecords() {
    const records = getAutoSaveRecords();
    if (records.length > 10) {
        const toDelete = records.slice(10);
        toDelete.forEach(record => {
            localStorage.removeItem(record.id);
            if (db) {
                try {
                    const stmt = db.prepare('DELETE FROM table_mappings WHERE id = ?');
                    stmt.bind([record.id]);
                    stmt.step();
                    stmt.free();
                } catch (error) {
                    console.error('删除自动保存记录失败:', error);
                }
            }
        });
    }
}

// 在关键数据操作后调用自动保存
function wrapWithAutoSave(originalFunction, ...args) {
    const result = originalFunction.apply(this, args);
    autoSave();
    return result;
}